OmniAICreator/Qiita-1.07M huggingface dataset:
航空宇宙における 3D スキャナーの用途と利点

3D スキャン技術は近年大幅な発展を遂げ、さまざまな業界で広く使用されています。特に航空宇宙分野では、3D スキャナーはその高精度、効率性、多用途性により、徐々に不可欠なツールとなっています。この記事では、航空宇宙分野における 3D スキャナーの具体的な用途と、それがもたらす多くの利点について説明します。

応用
1. リバースエンジニアリング
リバース エンジニアリングは、航空宇宙分野における重要なアプリケーション シナリオです。 3Dスキャナーにより、既存部品の高精度な3次元データを迅速に取得できます。このデータは、コンポーネントの再設計、改善、複製に使用できます。特に既存の CAD モデルが存在しない古い部品の場合、3D スキャン技術が特に重要です。
![bd6faee766ab3c97ec7d1f5041ca6245.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/93ada63c-958a-cf4a-af87-61ef29a6d2a3.png)

2. 品質管理とテスト
航空宇宙産業では、コンポーネントの品質要件が非常に厳しいです。 3D スキャナーは、製造された部品のフルスケール検査を実行し、スキャンされたデータを CAD モデルと比較して、寸法の偏差や欠陥を迅速に検出して、すべての製品が高い品質要件を満たしていることを確認できます。

3. メンテナンスと修理
航空宇宙機器の保守・修理作業には高い精度が求められます。 3D スキャナーを使用すると、部品の磨耗を検出し、耐用年数を評価できます。同時に、スキャンデータを使用して交換部品を製造したり、修理作業を指示したりすることもできるため、メンテナンス効率が向上し、ダウンタイムが削減されます。

4. 組立て検証
航空宇宙船の組み立てプロセスでは、さまざまなコンポーネントを正確にドッキングすることが重要です。 3D スキャン技術により、組み立て前に各コンポーネントをスキャンして、そのサイズと形状が設計要件を満たしているかどうかを検証できるため、組み立てプロセス中の問題を回避し、組み立ての効率と精度を向上させることができます。

![84fc9c55ce4815e0a98c1037ccc802b1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/fe1b3c1d-d259-4be9-f956-3bca3a2db900.png)
アドバンテージ
1.高精度
3D スキャナーは、ミクロンレベルの精度で非常に小さな詳細や複雑な形状をキャプチャできます。これは、航空宇宙部品の設計、検査、組み立てにおいて重要であり、各部品が厳しい精度要件を満たしていることを確認します。

2. 高効率
従来の測定方法では数時間、場合によっては数日かかる場合がありますが、3D スキャナーは同じ作業を数分で実行できます。これにより作業効率が大幅に向上し、製品開発・生産サイクルが短縮されます。

3. データの完全性
3D スキャナーは包括的な 3 次元データを取得できるため、従来の測定方法で発生する可能性のある欠落やエラーを回避できます。これらの完全なデータは、有限要素解析、流体力学シミュレーションなどのさまざまな解析やアプリケーションに使用して、全体的な設計および製造レベルを向上させることができます。

4. 柔軟性と多様性
3D スキャナは、小型の電子部品から大型の航空宇宙構造部品まで、さまざまなサイズや複雑な部品に適しており、さまざまなタイプの 3D スキャナで正確にスキャンできます。この柔軟性により、航空宇宙分野での幅広い応用の可能性が得られます。

5. 非接触測定
3Dスキャナーは通常、非接触測定方式を採用しており、測定対象物に損傷を与えることはありません。これは、測定プロセスの安全性と信頼性を確保するために、一部の精密部品や敏感な材料の測定では特に重要です。
![6b578fd883b0c52ba4fcaf142122bc48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/8dbc0840-6377-2fd9-b571-d6be8eae12c0.png)


3D スキャナーは航空宇宙分野での使用が増えており、その高精度、効率性、多用途性により業界に大きなメリットをもたらしています。 3D スキャン技術は、リバース エンジニアリング、品質管理、保守修理、組立検証などのアプリケーションを通じて、生産効率と製品品質を向上させるだけでなく、航空宇宙技術の継続的な進歩も促進します。技術のさらなる発展に伴い、航空宇宙分野における 3D スキャナーの応用の可能性はさらに広がるでしょう。

3Dスキャナーの選び方はこちらをご覧ください：https://www.revopoint3d.jp/blogs/blog/how-to-choose-scanner
FortiOS 7.4.1以降ではSSL-VPN設定がGUI上に表示されない件

## FortiGateでSSLVPN設定メニューが表示されない

これまでにFortiGateは何十台と設計・構築を行ってきたため
SSLVPNの設定は頭の中にインプット済みです。
たまたま構築案件があったためいつも通りFortiGateを起動して
GUIにログイン、SSLVPNの設定を開始しようとしたが…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2723699/f2125037-81a2-b8ae-ada6-f263851606c6.png)


SSLVPNの設定メニューがありません。

「あぁ、"表示機能設定"でSSLVPNがOFFになっているパターンか」と思い
確認してみたところ、ここにもSSLVPNが見当たらず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2723699/9e8a3564-41dd-167f-6b60-bf79994aa04d.png)

ネット上の技術系ブログ等も調べてみましたが、類似事象に関する情報が無かったためここに解決方法を共有しておきます。

## CLI上で設定メニュー表示の有効化が必要でした

Fortinet社のリリースノートを確認したところ、
どうやらFortiOS7.4.1以降では、SSLVPNのGUI設定がデフォルトで非表示になっておりCLI上で有効化する必要があるとのことでした。
▼FortiOS7.4 ReleaseNotes
https://docs.fortinet.com/document/fortigate/7.4.0/new-features/233856/update-ssl-vpn-default-behavior-and-visibility-in-the-gui-7-4-1

CLIより以下のコマンドを実行します。
```
config system settings
    set gui-sslvpn enable
end
```
画面を更新すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2723699/8a641e08-038b-9989-8ead-f39d64cf5826.png)

出てきました。
文字数制限と制限超過した場合は三点リーダ表示をした。（truncate関数あり）

![スクリーンショット 2024-08-05 14.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845129/94eead63-6602-f8d2-d6d0-54c787d9954a.png)
上のスクリーンショットは、文字列が5でmaxlengthになるように指定した。
```typescript:index.tsx
function truncate(str: string, len: number) {
  return str.length <= len ? str : `${str.substring(0, len)}...`;
}
const maxLength = 5;
```
同一のファイルの中で、適応させたい配列にtruncateとmaxLengthをかけるようにした。
```typescript:index.tsx
format: ({ value }) => truncate(value, maxLength)
```
これは他の場所でも使っていきたいのでJSXタグとして機能するようにした。
```typescript:index.tsx from Truncate
type Props = {
  str: string;
  len: number;
};
/**
 * @package
 */
export default function Truncate({ str, len }: Props) {
  return str.length <= len ? str : `${str.substring(0, len)}...`;
}
```
使用例：
```typescript
format: ({ value }) => <Truncate str={value} len={maxLength} />
```
HuggingFace ZeroGPU のRuntimeError:ZeroGPU: Unknownが出たら

こんにちはアッキーです。
Mixture-of-Agentsをgroq以外でも動くようにしたいと思って
https://huggingface.co/spaces/Akjava/llm-moa


今日から、ZeroGPUデビューしたところ、早速エラーの洗礼をうけました。


このエラーが出た場合は、運営に相談するしかない。(文章考えてる間に治ったので連絡はしてない)
```
raise RuntimeError("Error while initializing ZeroGPU: Unknown")
RuntimeError: Error while initializing ZeroGPU: Unknown
```

特徴としては、コードがアノテーション部分に到達した瞬間にエラーが出ます。
sleepとか対処法考えましたけど無駄でした。時間が解決するタイプの問題ですね。
```
@spaces.GPU
def generate_text(
```
悲しいかな、別のSpaceを作っても同様のエラーでした。次からは、@spaces.GPUのアノテーションを外して、CPUモードで見た目とかの検証に時間を当てたいと思いました。


Issue的には未解決だけどこれかも
https://github.com/hpcaitech/Open-Sora/issues/532

未確定ですが、Modelを再利用しようと試みるとこのエラーになったケースもあった。読み込み時間かかってしかたないけどモデルはGPUメソッド内で作り直すことにする。

## もしかして
少しだけ謎が解けてた。@spaces.GPU以外のところでも、間違ってGPU取得できたりするけど、それしたら後でクラッシュが待ってると思うことにする。
@spaces.GPU以外のメソッドでGPUに触れないことだね。
面倒だけど、modelもpipelineも毎回初期化するしかないかな。(時間できたら人気アプリの構成を見てみよう)

## その他のエラー
import spaces の位置を変えたら治った?
```
/usr/local/lib/python3.10/site-packages/torch/cuda/__init__.py:628: UserWarning: Can't initialize NVML
  warnings.warn("Can't initialize NVML")
Traceback (most recent call last):
  File "/home/user/app/app.py", line 4, in <module>
    import spaces
  File "/usr/local/lib/python3.10/site-packages/spaces/__init__.py", line 19, in <module>
    from .zero.decorator import GPU
  File "/usr/local/lib/python3.10/site-packages/spaces/zero/__init__.py", line 15, in <module>
    raise RuntimeError(
RuntimeError: CUDA has been initialized before importing the `spaces` package
```
React初学者の振り返り

# はじめに
Reactを学び始めたので気になったものを書き出してく

## memo
Reactは親コンポーネントのstateが更新された際に子コンポーネントも再レンダリングされる。
これを防ぐのがmemo。
propsが変更されていない場合にコンポーネントの再レンダーをスキップできるReactの機能。
```react:
import {memo} from "react";
memo(コンポーネント);
```

## useCallback
コールバックで関数を呼ぶ際、アロー関数で関数を定義した場合その都度関数を定義した扱いとなり際レンダリングが走ってしまう。
memoを用いてコンポーネントのレンダリングをスキップしても、そのせいで再レンダリングが起きてしまう。
これを防ぐのがuseCallback。
再レンダー間で関数定義をキャッシュできるようにするReactフック。
```react:
import { useCallback } from 'react';

useCallback(function,[states] )
```
yukicoder No.65 回数の期待値の練習　解説

[問題文](https://yukicoder.me/problems/no/65)

# 解説
今回の問題のユーザー解説はみんな動的計画法動的計画法言っていたので、私は再帰関数を使った解説にする。

```math
f(x) = \left\{
\begin{array}{ll}
(E(x+1)+E(x+2)+E(x+3)+E(x+4)+E(x+5)+E(x+6))\times \frac{1}{6}+1(X<K)&(X<K)\\
0&(X\geqq K)
\end{array}
\right.
```
これをそのままいい感じに解けばよい。
$K=20$のとき、下記のコードによる$E$の呼び出し回数は$2830273$回と十分に少ないので、わざわざメモ化再帰する必要もない。

# C++での再帰関数解答例
```C++
#include <bits/stdc++.h>
using namespace std;

double E(int x,int K){
  if(x>=K)return 0;
  return (E(x+1,K)+E(x+2,K)+E(x+3,K)+E(x+4,K)+E(x+5,K)+E(x+6,K))/6+1;
}

int main(){
  int K;cin>>K;
  cout<<fixed<<setprecision(20);
  cout<<E(0,K)<<endl;
}
```

また、せっかくなのでメモ化再帰についてもやってみる。
再帰関数$E$の前にメモ用配列を用いて、すでにその数値を呼び出していたならそれをそのままリターンする、

メモ化再帰解答例
```C++
#include <bits/stdc++.h>
using namespace std;

//メモ化再帰用配列
vector<double> memo(30,-1);
double E(int x,int K){
  if(x>=K)return 0;
  if(memo[x]!=-1)return memo[x];
  double c=(E(x+1,K)+E(x+2,K)+E(x+3,K)+E(x+4,K)+E(x+5,K)+E(x+6,K))/6+1;
  memo[x]=c;
  return c;
}

int main(){
  int K;cin>>K;
  cout<<fixed<<setprecision(20);
  cout<<E(0,K)<<endl;
}
```
EC-CUBEご注文手続きページ本文＆ドロップダウンの英語化

# 基本環境
EC-CUBE4.2.3

# twig 修正
```:root/app/template/default/Shopping/index.php

// <h1>{{ 'ご注文手続き'|trans }}</h1>
<h1>{{ 'Purchasing Procedure'|trans }}</h1>

その他日本語　→　英語
```
# Type.php 修正
```:root/src/Eccube/Form/Type/Shopping/ShippingType.php
// 'ja_JP@calendar=japanese',
'en_US@calendar=english',

// 'placeholder' => 'common.select__unspecified',
'placeholder' => 'Unspecified',


// 'placeholder' => 'common.select__unspecified',
'placeholder' => 'Unspecified',
```
mysqlでストアドプロシージャの書き方のメモ

## ストアドプロシージャとは

ストアドプロシージャはどうやらSQLで手続き的な関数が定義できるぽいので、これは便利そう！と思いちょっとしらべてみました。

ストアドプロシージャの利点
1. 再利用性：一度作成すれば、何度でも呼び出して使用できます。
2. パフォーマンス：クライアントとサーバー間の通信を減らし、サーバー側で処理を行うため、パフォーマンスが向上します。
3. セキュリティ：データベース操作をカプセル化することで、直接SQL文を実行するよりも安全です。

## サンプル
```
DELIMITER //

CREATE PROCEDURE GetUserByEmail(IN userEmail VARCHAR(255))
BEGIN
    SELECT * FROM users WHERE email = userEmail;
END //

DELIMITER ;

        
```
# 以下各行の解説

### ・DELIMITER//とは
デリミタ（sqlの終端を表す文字）を”；”　から”//”変更して、プロシージャ内のsqlで記載した";"をプロシージャの最終文字と被らないようにする為の一行。

### ・CREATE PROCEDURE
GetUserByEmail(IN userEmail VARCHAR(255))：GetUserByEmailという名前のストアドプロシージャを作成します。INパラメータuserEmailを受け取ります

### ・BEGIN ~ END
プロシージャの本体を定義します。

### ・ `SELECT * FROM users WHERE email = userEmail;`
`users`テーブルから指定されたメールアドレスのユーザーを選択します。

### ・`DELIMITER ;`
デリミタを元に戻します。

## ストアドプロシージャの実行　
CALL ストアドプロシージャ名（）で実行できます。



***
:::note info
javascriptでプロシージャーを定義する方法もあるみたいです。　　時間があればすこし遊んでみます。
:::

https://blogs.oracle.com/mysql/post/introducing-javascript-support-in-mysql
vCenter Serverの パスワードポリシーの変更

# 1.vSphere 管理ユーザのパスワードポリシー変更
[三]-[管理]-[Single Sigh-On]-[設定]に移動する
[ローカルアカウント]切替え、[パスワードポリシー]の変更をクリックする

![vSpherePasswordPolicy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425858/0b9ed4fa-7a26-a20d-3ad8-74342ac3cfb2.png)

# 2.rootユーザのパスワードポリシー変更

TeraTermでSSH接続する（SSH接続できるならなんでも）

```
> shell
```

```
> vi /etc/pam.d/system-password
```
yukicoder No.64 XORフィボナッチ数列　解説

[問題文](https://yukicoder.me/problems/no/64)

# 解説
まず、$F$の要素を一つずつ調べてみる。
すると、計算量は$O(N)$なので、余裕でTLEする。
ここで、$F_0=A,F_1=B,A \oplus B=C$とする。
$A \oplus B=C,A \oplus C=B,B \oplus C=A$なので、実は$F$は次のように並ぶ。
$A,B,C,A,B,C,A...$こんな感じに。
よって$N mod 3$の数によって判定すればよい。
$F_0,F_1$が$10^{18}$と十分に大きいので注意。

# C++での解答例
```C++
#include <bits/stdc++.h>
using namespace std;
using ll=long long;

int main(){
  ll F_0,F_1,N;cin>>F_0>>F_1>>N;
  if(N%3==0)cout<<F_0<<endl;
  if(N%3==1)cout<<F_1<<endl;
  if(N%3==2)cout<<(F_0^F_1)<<endl;
}
```
改行コードに関するトラブルシュート

### 環境

Ubuntu20.04
Ruby2.7

### はじめに

Ubuntu環境でRubyを実行したところ、つぎのエラーが表示されたため、そのトラブルシュートになります。

```
ruby: warning: shebang line ending with \r may cause problems
```

### 原因

エラーの内容は
「改行コードに\rが使われてると、問題を引き起こす可能性があります」という意味です。エディタで改行コードを見てると、**CRLF**と表示されます。CRLFはWindowsで利用される改行コードです。CRLFで作られた改行コードをLinux上で動かしたためにエラーが発生しました。

Linuxで動かすにはLinux用の改行コードに変換する必要があります。開発はWindoes環境で行い動作環境はUbuntuといった、ハイブリッド環境を使っていると、このような問題が発生しました。

### 改行コードを変換する

現状の改行コードを確認するコマンドです。改行部分が、**\r\n**で表示されていれば、Windows用の**CRLF**になっています。

```
$od -c hoge.rb
```

改行コードを変換するコマンドです。nkfは富士通が開発した文字コードを変換するための有名なツールです。これを使って、改行コードも変換することができます。

```
$nkf -Lu hoge.rb > hoge_lf.rb
```

変換後の改行コードを確認します。改行部分が、**\n**で表示されていれば、Linux用の**LF**になっています。

```
$od -c hoge_lf.rb
```

### VS Codeで直す

VS Codeを使って改行コードをCRLFからLFに直すこともできます。やり方はいたって簡単です。改行コードはVS Codeの右下のバーに表示されます。そこをクリックして、改行コードのプルダウンメニューからLFを選択します。その後、更新すれば、改行コードをLFになっています。
yukicoder No.63 ポッキーゲーム　解説

[問題文](https://yukicoder.me/problems/no/63)

# 解説
まず、一回齧ると$2 K$減る。$L < 2K \times 操作回数$になると操作ができなくなる。そこから、操作できる回数は$\lfloor (L-1) \div 2K \rfloor$となる。よって答えは$\lfloor (L-1) \div 2K \rfloor *K$。これを出力すればよし。

# C++での解答例
```C++
#include <bits/stdc++.h>
using namespace std;
using ll=long long;

ll downfloor(ll x,ll m){
  // x/mを正確に求める関数
  ll r=(x%m+m)%m;
  return (x-r)/m;
}

int main(){
  int L,K;cin>>L>>K;
  cout<<downfloor(L-1,2*K)*K<<endl;
}
```
applescriptでmruby/cを焼いてみた

10秒以内にxmodem送信準備ができないと失敗するので、スクリプトにしてみました。

```applescript
tell application "Terminal"
	activate
	set usbdev to do shell script "ls /dev/cu.usb*" -- CDC and FDTI device
	do script "cd /Users/hiroki/Develop/mruby/mruby-3.3.0-mac" in front window
	do script "screen " & usbdev & " 38400" in front window
	delay 2
	tell application "System Events"
		tell process "Terminal"
			-- input method on ascii
			key code 41 using {control down, shift down}
			-- monitor command
			keystroke "x"
			delay 1
			-- screen command
			key code 0 using {control down}
			delay 1
			keystroke ":"
		end tell
	end tell
	do script "exec !! /Users/hiroki/Develop/Z80/xm/xs hoge.mrb" in front window
end tell
```

ちゃんとリトライとタイムアウトを実装するのが正しいのですが、暑いのでこんなばかばかしいことしかできません。
【C#】呼出し元のオブジェクトが破棄される場合のイベント購読解除の要否について

# 概要
C#にて、イベントを購読した後、イベントを発行するオブジェクトがnull代入等で破棄される場合は、購読の解除が不要そうでしたので、備忘録として纏めました。

# 内容
例えば、以下のようなイベント接続をしている場合があったとします。

```C#
public class ClassA
{
    private ClassB _classB;
    
    private void Execute()
    {
        _classB = new ClassB();
        _classB.OnSampleMethod += this.SampleMethod;  // イベント接続
    }
    
    private void SampleMethod(bool result)
    {
        // 何かしらの処理
    }
}
```

```C#
public class ClassB
{
    public delegate void SampleHandler(bool result);

    public event SampleHandler OnSampleMethod;

    private void Method()
    {
        bool result = true;
        OnSampleMethod(result);
    }       
}
```
上記の場合、例えばイベントを発行する側のオブジェクト (ここではClassAのフィールドである`_classB`) が、例えば`_classB = null`等で破棄された場合については、
破棄される前に登録解除 (ここでは、`_classB.OnSampleMethod -= this.SampleMethod;`) は行わなくても良さそうでした。
※間違っていたらご指摘ください。
***

参考にしたURL：

https://stackoverflow.com/questions/4172809/should-i-unsubscribe-from-events

https://gamedev.stackexchange.com/questions/204735/is-it-necessary-to-unsubscribe-from-c-events-when-the-event-owner-has-already-b
【初心者向け】コーディングを行うための環境構築

## コーディングを始める前に
HTMLやCSSを実際に書いてみたい！
と思ったら、まずは環境の準備が重要です。

## エディタを用意しよう！
#### エディタとは
コンピュータ上で何らかのデータを編集するためのソフトウェア。 
文字データを扱うソフトはテキストエディタと呼ばれ、文字の種類や大きさ、
修飾などが不要なプログラミング時のソースコード作成・編集に用いられることも多い。
統合プログラミング環境における、プログラムを作成する機能を、エディタと呼ぶ場合もある。

ちょっとわかりにくいかもですが、
プログラミングのコードを書くためのソフトウェアのこととなります。

メモ帳（Windows）とかテキストエディタ（MAC）とかでも
書けないことはないですが…かなりみにくいです。

そのため、まずは自分に合ったエディタを探してみましょう！

#### エディタを選ぶためのポイント
・対応しているプログラミング言語が何か
・対応しているOSは何か
・日本語対応しているか
・動作の軽さ
・各種機能の有無

特に初心者の方は、
日本語対応とか、対応しているOSの種類だけ最低限押さえておけば良いと思います。

## 現在のおすすめエディタ
#### Visual Studio Code
Atomとともに現役プログラマーの大きなシェア。
HTMLやCSS、Javascriptなど数多くのプログラミング言語をカバーする汎用性の高さも魅力。
初心者向けのエディタとしてもおすすめ。
（最近はこちらを紹介している動画やサイトが多いように感じたので、現在こちらをインストールして使用してみてます）

Visual Studio Code：https://code.visualstudio.com/

#### Atom
MacやWindows、Linuxに対応しており、シンプルかつ見やすい。
これからプログラミングを始める超初心者からプロまで満足できる柔軟性あり。
(プログラミングスクールに通ってた時はこちらをおすすめされて一時期使ってました)

Windows版：https://atom.softonic.jp/
MAC版：https://atom.softonic.jp/mac

#### Sublime Text
プラグインが非常に充実しており、目的に合わせた高度なコーディングにも対応可能。
ハイライトやgrep(文字検索)機能に加えて、複数の文字列の同時編集やなど多彩な機能が魅力。
Sublime Textは本来有料ソフトウェアですが、すべての機能を無料で利用できます。
（少し前まではこちらを使用していました）

Sublime Text：https://www.sublimetext.com/3

#### PyCharm
Python言語向けのコードエディタ、および統合開発環境(IDE)。
無料の「コミュニティ版」でもエラー検出やハイライトなどの重要な機能はすべて使用可能。
これからPythonを習得してビジネスの幅を広げたい方には特におすすめです。

PyCharm：https://www.jetbrains.com/ja-jp/pycharm/

#### サクラエディタ
OSはWindowsにのみ対応。
分からない部分は日本語フォーラムですぐに解決できる。
一からコーディングを勉強したい初心者にはとても心強い存在。

サクラエディタ：https://sakura-editor.github.io/

#### Notepad++
Windowsの標準メモアプリを強化したような簡潔なインターフェースが特徴的。
低スペックのPCでも安定して動作する軽快さが魅力。
初心者向けの無料コードエディタとして常に候補に挙がる人気のソフトウェア。

Notepad++：https://notepad-plus-plus.org/downloads/



#### これまでの記事の参考サイト：https://brik.co.jp/tips/322#i-4




### 気になったエディタがあれば、早速インストールしてみましょう！！
Realtekのドライバをubuntuに入れようとしてうまくいかなかった話

# RTL8126はUbuntu 22.04では、ドライバを入れないと動かない

最近のPCをゲットしたので、Ubuntu入れてさー使うぞー。って思ったら有線LANポートが機能していない。

チップはなんやねん

```shell
$ lspci
...
Ethernet controller: Realtek Semiconductor Co., Ltd. Device 8126 (rev 01)
...
```

蟹やん。最近のIntelチップはイマイチっぽいけど、最近の蟹はそんな評判悪くないんだけどなー。ま、ドライバ入れるかー。

と、[蟹のDownloads](https://www.realtek.com/Download)からドライバを引っ張ってくる

> 5G Ethernet LINUX driver r8126 for kernel up to 6.4

これやな。とおもむろにダウンドードして`tar`コマンドで解凍する。中を見ると`README`,`autorun.sh`...お、なんかいい感じやん。

# Trueエンド

と思いつつREADMEをチラ見すると`Requirements`に`Kernel source tree`と書いてあるので、まずは linux-headersをインストールする

```shell
$ sudo apt install linux-headers-$(uname -r)
```

この後にREADMEに倣い

```shell
sudo ./autorun.sh
```

を実行すると使えるようになる。gcc-12がないと言われたらインストールして再度実行すれば良い。

# ゲームオーバーエンド

と思いつつREADMEをチラ見すると`autorun.sh`をsuかsudoで実行してよーって書いてある。

おぉ、親切じゃんと思いつつ

> sudo ./autorun.sh

だけど`/lib/modules/[カーネルバージョン]/build`がないと言われる。そりゃないんだからと`mkdir`で作ってしまうと

> make[2]: *** No rule to make target 'clean'. Stop.

というエラーに悩まされることとなる。そう、buildは本来linux-headersをインストールしたときに生成されるシンボリックリンクだったのです。
Trueエンドに辿り着くにはbuildディレクトリを削除してからlinux-headersをインストールしましょう。
え、linux-headersをインストールしちゃった？じゃあbuildディレクトリを削除してからシンボリックリンク貼ってください。こんな感じで

```shell
sudo ln -s /usr/src/linux-headers-$(uname -r) /lib/modules/$(uname -r)/build
```

だいぶ遠回りしちゃいました。まぁ、よくあることです。とほほ。
AWS DeepRacerに初挑戦しました！

## はじめに
新人研修にてAWS DeepRacer研修が行われました。

DeepRacerとは、Amazonが提供するクラウドサービスAWS上で作成した強化学習のモデルを使用し、シミュレータやレーシングカーを使用してレースを行うサービスです。
二日間に亘って研修が行われ、今回の研修で初めて、DeepRacerを体験して強化学習に触れることができました。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845354/6d406c03-e6d3-9eea-acbc-f6e8a326260b.png)

## 概要
AWS DeepRacer研修では、３種類のコースがレース会場に用意されていました。

仮想環境でそれぞれのコースに適応するための学習を行い、シミュレーションを繰り返すことでよりよいモデルを構築していきます。

コースを速く、安定的に走行させるためにどのようなパラメータ設定が適切か、学習させるコースについても様々な特徴を持つコースから検討を行います。

その後、実環境での走行練習を経て出た課題を、プログラムの変更や学習させるコースの選択によってさらなる改善を行っていきます。
最終日の二日目は、大会形式でコース一周のタイムを競い合いました。

（研修の様子）
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845354/ddf8073c-0ae0-94bb-94ea-e4713a60716f.jpeg)


## 学習のさせ方と工夫した点
まず、仮想環境でシミュレーションを行っていきます。

最初のシミュレーションでは、「カーブでのコースアウトを避け、最後まで走り切る」という目標を立て、目標を実現するために以下のように設定を行いました。


- 報酬関数：Time trial – follow the center line（既定値）
中央線に近い走行をしたときに高い報酬を与え、中央線から離れるほど報酬が少なくなる。
- ハンドルを切る角度：左右それぞれ30度
- スピード：下限1m/s、上限2m/s
暴走を防ぐため、速度差をできるだけ抑えて設定

仮想環境でのシミュレーションでは、コース一周のタイムは最初約30秒でしたが、1時間の学習を３回ほど繰り返すと、タイムは約15秒にまで短縮されていきました。

## 実環境で走らせてみた
今度は、学習させたモデルを実際のコースで走らせてみます。
コースはRL Speedway、急なカーブとゆるやかなカーブを含んだコースです。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845354/d89fd999-3c8b-47b4-92cc-4fa1319c3f06.png)


走らせた結果、曲がり方は中心の線に沿うように曲がり、直線では中央線に沿ってジグザグにぶれが生じている印象がありました。

また、課題として以下の2点があげられました。
- ゆるやかなカーブでコースから外れてしまう（同じ個所）
- 直線では、スピードを出したい

特に一つ目の緩やかなカーブのコースアウトは仮想環境では、見られなかった課題でした。
学習時間が限られていたため、コースアウトの回数が少ないモデルのクローンを作成し、各設定を変更したモデルをいくつか作成し、より優れたものを選定することとしました。

課題を受けて変更した点は以下の通りです。
- ゆるやかなカーブでコースから外れてしまう（同じ個所）
    - ゆるやかなカーブを持つコースを複数学習させ、モデルの汎化を試みた

また、直線でスピードを出すにはスピードの変更が必要でしたが、コースアウトにつながるため、リモコンの操作で直線走行時にスピードの調整を行うことにしました。

## 本番での走行

本番の走行では、RL Speedwayのコースで走行を行いました。
課題としていたゆるやかなカーブでのコースアウトは、やはり曲がり切れず、課題として残りました。

コースアウトした実機をコース上に戻す役割のメンバーを本番ではその位置に配置し、コースアウトしたら即復帰が行えるようにしていました。
指導員の方の話によると、実環境の走行は仮想環境にできるだけ近い状態にする方が好ましく、カーブの位置に人が立っていると、学習の結果を上手く走行に反映できなくなってしまい、良くないということでした。

しかし、それ以外の走行はシミュレーション通りスムーズに走ることができ、シミュレーションのタイムと同じ15秒で一周することができました。

（実機走行の様子）
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845354/338c6c6e-ff0d-e831-de15-3f13e55258e5.png)


## 終わりに

研修ではモデルを以下の工程を繰り返して構築していきました。

1.	強化学習を行うための報酬関数、各パラメータの設定
2.	シミュレータを利用した仮想環境でのモデルの走行
3.	実環境での実機の走行
4.	仮想環境と実環境のギャップをなくすための改善

特に4番は学習させたことが想定通りに生かせていない、全く違う挙動をしているなど、研修中で一番苦労した点でもありました。

これらの経験からAWS DeepRacer研修に参加して、強化学習においては以下の3点が特に大切だと実感しました。

- 実機はカメラから得た情報を入力としていたため、カメラに映るものは、学習した環境に近い映像の方がよい。
人が映り込むと障害物は学習させていないため、走行を妨げる可能性がある。

- 仮想環境と実環境では床とタイヤの摩擦などの物理的要因に違いがあるため、それらを考慮する。
実環境ではリモコン操作でスピードの調整をあらかじめ行った。

- できるだけ実環境を意識した学習をさせる。
走行するコースの特徴に合わせ、ハンドルを切る角度が小さいほうが良いのか考え、それに伴ってスピードの設定を行い、学習させるコースを選定した。

AIは学習のさせ方によって、与えられた課題に特化したり、様々課題に順応できるよう汎化したりと違いが出てくるので、最終的に何をクリアさせたいのか目的を明らかにしておく必要があると感じました。

今回の研修でAIが最初は克服できなかった課題を徐々にクリアして成長していく過程に面白さを感じることができ、とても貴重な体験になりました！
【amplify gen2】cognitoログイン後とログイン前のユーザーのデータ取得権限を切り分ける

# はじめに
amplify gen1 から gen2になり iam認証というものが無くなっていてschemaの書き方で困ったのでまとめます。

# 問題
amplify gen1でauthルールのiamを使えば、ログイン前後の権限を切り分けることが出来ていたがgen2だと書き方がわからない
amplify gen2の書き方だとCognitoで認証済みのユーザーの権限と認証前のユーザーのデータ取得権限が変わらない

```graphql
# amplify gen1 で書いていた書き方
type Table @model @auth(rules: [
    { allow: public, provider: iam, operations: [read] },
    { allow: private, provider: iam, operations: [read, create, delete, update] }
]) {
 id: ID!
 ...etc
}
```
### 解決前コード
```typescript
// /amplify/data/resource.ts
const schema = a.schema({
    Table: a
    .model({
        column: a.string
    })
    .authorization((allow) => [
        allow.authenticated(),
        allow.guest().to(['read']),
    ]),
})

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'userPool',
  },
});
```

```typescript
// /amplify/auth/resource.ts
...
export const auth = defineAuth({
  loginWith: {
    email: true,
  },
});
```

### 出力されたエラー
↓ 認証前ユーザーのコンソール
※認証後のユーザーでは、権限が付与されているのを確認できている
```
POST *** 401 (Unauthorized)
```

# 解決方法
上記の/amplify/data/resource.tsを記載を変更
下記のように書くことで、cognitoのログイン後のユーザーはTableのCRUD権限を持つ。ログインをしていないユーザーに対しては、Read権限のみ付与するという書き方が出来ました。

```typescript
// /amplify/data/resource.ts
const schema = a.schema({
    Table: a
    .model({
        column: a.string
    })
    .authorization((allow) => [
      allow.authenticated('identityPool'),
      allow.guest().to(['read'])
    ]),
})

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'identityPool',
  },
});
```

# おわりに
amplify gen1 からgen2になり書き方が変わって戸惑っていますが、今の書き方が慣れれば簡単かもですね

# 参考
https://docs.amplify.aws/react/build-a-backend/data/customize-authz/signed-in-user-data-access/
tRPCを利用してBackendからFrontendまで統一的な型適用

# 対象とする読者
- tRPCを活用したいと思っている人

# tRPCとは
tRPCとは、TypeScriptで書かれた高速なRPC（Remote Procedure Call）フレームワークです。tRPCを使用すると、スキーマやコード生成なしに型安全なAPIを簡単に構築および利用できるようになります。特に、Next.jsとの連携が容易であり、サーバーサイドでのAPIの構築を簡単にします。
※Copilotより

# tRPCの基本的な型参照
具体的に記載するとリンク先にあるように

https://trpc.io/docs/quickstart#2-querying--mutating

InputにもOutputにも型が付きクライアント・サーバー間で統一的に型を利用できます
例：query
Input：string
Output：user型
```ts
// Inferred types
const user = await trpc.userById.query('1');
       
const user: {
    name: string;
    id: string;
} | undefined
```

例：mutation
Input：{ name : string }
Output：createdUser型
```ts
const createdUser = await trpc.userCreate.mutate({ name: 'sachinraja' });
          
const createdUser: {
    name: string;
    id: string;
}
```

- 簡単なコンポーネントであれば、同じコンポーネント内で参照すればよいので、問題になりませんが、大体はコンポーネント分割してInputやOutputをパラメータとして参照したくなります 

つまり
```tsx
const user = await trpc.userById.query('1');

return <Profile user={user} />
// としたときに
---

interface Props {
  user : XXX
}
export const Profile: React.FC<Props> = (props) => {
// XXXが必要になります
```

DBから直接User型を持ってくることもできますが、userのパラメータが絞られていたりする場合に、絞り込むTypeを各Frontでも書く必要になり2度手間になります。

のでtRPCを介したINPUT,OUTPUTをそのまま型として参照したい

# tRPCのOUTPUT型を参照する

tRPCのinferRouterOutputsを利用する

- Type定義

```ts
import { type inferRouterOutputs } from "@trpc/server";

export type RouterOutput = inferRouterOutputs<AppRouter>;

export type GetTodoOutput = RouterOutput["todo"]["getTodo"];

```

- Reactでの利用
 
```tsx
const todo = await trpc.todo.getTodo.query('1');

return <Todo todo={todo} />
---

interface Props {
  todo : GetTodoOutput
}
export const Todo: React.FC<Props> = (props) => {
   const { todo } = props
   // tRPCのgetTodoのOutput型にアクセスできる
   console.log(todo.id)
```
- もしOutpuの中のオブジェクトをパラメータで渡したい場合の型参照

```tsx
interface Props {
  obj : GetTodoOutput["someObj"]
}
export const Todo: React.FC<Props> = (props) => {
   const { obj } = props
   // tRPCのgetTodoのOutput型のオブジェクトにアクセスできる
   console.log(obj.data)
```


# tRPCのINPUT型を参照する

tRPCのinferRouterInputsを利用する

- Type定義

```ts
import { type inferRouterInputs } from "@trpc/server";

export type RouterInput = inferRouterInputs<AppRouter>;

export type PostTodoInput = RouterInput["todo"]["postTodo"];

```

- Reactでの利用
 
```tsx
const postMutation = await trpc.todo.postTodo.mutation('1');

const onSubmit = ()=>{
   // パラメータの型を指定できる
   const params: PostTodoInput = {
      title: "todoTitle",
      description: "todoDescription"
   }
   postMutation.mutate(params)
}

```
リストをカンマ区切りの文字列にしたい

使うたびに調べているので、自分用のメモとして記します。

# やりたいこと
リストをカンマ区切りの文字列にしたい

## 具体例
```python
todofuken = ["北海道", "青森", "秋田", ....,"沖縄"]
```
上記のtodofukenリストを`北海道,青森,秋田,....,沖縄`という文字列にしたい。

# やり方

## コード
```python
todofuken = ["北海道", "青森", "秋田", ....,"沖縄"]

# カンマ区切りで結合
text = ','.join(todofuken)
print(text) 
```

## 実行結果
```
北海道,青森,秋田,....,沖縄
```
DisplayModeを変える


フローでステータスを変更しているので、手動で変えられないように編集不可にしてみたい。
どうもDisplayModeをDisplayMode.Viewにすればいいみたい。


今の設定を確認するとParent.DisplayMode　... 親の設定を見ている？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/27278f7f-8472-9041-1725-739b7a9523cc.png)

では、この親は？　Parent.DisplayMode　？　さらに親？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d83ed11f-5dfc-ab6f-a31c-5b54b4c807ca.png)

DisplayMode自体がない。　もう深く考えるのは止めます。どうもMSさんのシステムは理解できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f72a774f-26e0-a6a8-5bb4-d51c53f6c124.png)


ああああ、変更できない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/da894cb3-e524-b921-d897-37209a12f034.png)

https://blog.jbs.co.jp/entry/2024/03/25/111033#:~:text=%E3%81%BE%E3%81%9F%E3%80%81%E8%A7%A3%E5%83%8F%E5%BA%A6%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B,%E3%82%92%E3%81%97%E3%81%A6%E5%AE%8C%E4%BA%86%E3%81%A7%E3%81%99%E3%80%82


「読み取り専用エディターでは編集できません」と表示されてしまう場合、画像上で右クリックをし、「ロック解除」をクリックします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e5efcefc-575c-c2ba-c6c0-dcc2215f6fb1.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3af441e6-5e47-4287-f542-f09525c803e9.png)

# コピーできる部品とそうでないのがある？

右クリックしてコピーがある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/fa7385a2-7307-71dc-750b-d170751bf29a.png)

ロックを解除したけど、コピーはない。
次のページに移動させたいけどできませんね。本当このツールは使いにくい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1a4ca754-c2d5-a201-aefb-919ca4a934e4.png)
Databricksのストリーミングテーブルを動かしてみる

以前こちらのマニュアルを訳していました。

https://qiita.com/taka_yayoi/items/c3186e6c64413751b0ed

ですが、動かしていなかったので、改めて作成から動作確認までをウォークスルーします。

マニュアルはこちら。

https://docs.databricks.com/ja/tables/streaming.html

# ストリーミングテーブルとは

> Databricks では、Databricks SQL を使用してデータを取り込むためにストリーミング テーブルを使用することをお勧めします。 ストリーミング テーブルは、ストリーミングまたは増分データ処理の追加サポートを備えた Unity Catalog マネージドテーブルです。 Delta Live Tables パイプラインは、ストリーミング テーブルごとに自動的に作成されます。 ストリーミング テーブルを使用して、Kafka およびクラウド オブジェクト ストレージからの増分データ ロードを行うことができます。

データソース(オブジェクトストレージやメッセージングシステム)に新規データが到着した際に、増分のみを取り込むことができるテーブルです。すでにDelta Live Tablesで実装されていた機能が、Databricks SQLからも利用できるようになったという背景があります。

# ストリーミングテーブルの作成

ストリーミングテーブルを作成する際にはデータソースを指定する必要がありますが、オブジェクトストレージを指定する際にはデフォルトではオブジェクトストレージにファイルが存在している必要があります。

ですので、以下のようなファイルをボリュームにアップロードしておきます。ここでのパスは、`/Volumes/users/takaaki_yayoi/landing`となります。

```one.csv
id,name,age
1,taka,51
2,polka,8
```

スキーマ推定の際に数値がintに識別されるように、カンマの前後に空白を含めないようにします。

SQLノートブックあるいはSQLエディタで以下を実行します。

```sql
USE users.takaaki_yayoi;
```
```sql
CREATE
OR REFRESH STREAMING TABLE streaming_test AS
SELECT
  *
FROM
  STREAM(
    read_files('/Volumes/users/takaaki_yayoi/landing')
  )
```

処理が成功したらテーブルを確認します。

```sql
SELECT * FROM streaming_test;
```
![Screenshot 2024-08-05 at 12.55.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4d14adca-2dec-57ba-0eab-51edc6048b08.png)

`_rescued_data`は、背後で動いているAuto Loaderによって作成されたものです。詳細は[こちら](https://docs.databricks.com/ja/ingestion/auto-loader/schema.html#rescue)をご覧ください。

# ストリーミングテーブルの更新

二つ目のファイルをボリュームにアップロードします。

```two.csv
id,name,age
3,ume,9
4,yuki,5
```

ストリーミングテーブルを更新します。

```sql
REFRESH STREAMING TABLE streaming_test;
```

```sql
SELECT * FROM streaming_test;
```
![Screenshot 2024-08-05 at 12.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4af08961-545f-0eb8-f49c-1e1670eca158.png)

ストリーミングテーブルを作成すると、そのテーブルを更新するためのDelta Live Tablesパイプラインが作成されます。カタログエクスプローラでストリーミングテーブルを表示すると、**更新の詳細を参照**からDLTパイプラインを確認することができます。
![Screenshot 2024-08-05 at 12.45.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cfc5ac3a-2a96-2dbc-ff8f-c11449059a4b.png)
![Screenshot 2024-08-05 at 12.45.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/045c768c-ecbd-ba6a-beb6-ae2b72dfe8d9.png)

SQLリファレンス(英語)は[こちら](https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-ddl-create-streaming-table.html)です。

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
var targetList = new List<string>(); という記述についての個人的な好みを紹介してみる。

次の 2 通りの宣言方法は
どちらが見やすいでしょうか？

```Csharp
var targetList = new List<string>();
List<string> targetList = new();
```

やっている事は同じなのですが
私は targetList が List＜string＞ 型だと
すぐに分かる後者の方が
分かりやすいと思っています。

後で見直した時に
targetList が何型か知りたくなった時に
後者の方が若干早いという考え方です。

var を使用する箇所が増えると
型を解析するための微量の時間が蓄積して
結果的に解析に時間がかかるイメージがあります。

***

また、めったに無いですが
メソッド名から型の推測が難しい場合、例えば

```Csharp
var targetPoints = Cv2.FindContoursAsArray(Edge_Canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
```

よりは

```Csharp
OpenCvSharp.Point[][] targetPoints = Cv2.FindContoursAsArray(Edge_Canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
```

の方が分かりやすいと思っています。

どちらもほとんど同じかもしれませんが、
皆さんはどちらの方が見やすいと思いますか？

是非意見を頂けると嬉しいです。

短いですが今回はここまで。
閲覧ありがとうございました。
FlaskのBlueprintの役割

# 質問1
Blueprintについて，単にregister，login，logoutにかかわる内容を記述したauth.pyモジュールを__init__.pyにてインポートするだけでいいと思った．単にインポートするのと何が違うのか？

<br>

## 回答

Blueprintを使用することと、単にモジュールをインポートして関数を登録することにはいくつかの重要な違いがあります。それぞれの方法の違いと、Blueprintを使う利点を説明します。

## 単にモジュールをインポートして関数を登録する場合
たとえば、`auth.py` モジュールに認証関連のビュー関数を定義し、それを`__init__.py` でインポートして直接登録する場合を考えます。

```python
# auth.py
from flask import Flask, request, redirect, url_for

def register():
    # ユーザー登録に関する処理
    pass

def login():
    # ログインに関する処理
    pass

def logout():
    # ログアウトに関する処理
    pass
```

``` python
# __init__.py
from flask import Flask
from .auth import register, login, logout

def create_app():
    app = Flask(__name__, instance_relative_config=True)

    app.add_url_rule('/auth/register', 'register', register, methods=['GET', 'POST'])
    app.add_url_rule('/auth/login', 'login', login, methods=['GET', 'POST'])
    app.add_url_rule('/auth/logout', 'logout', logout)

    return app
```

## Blueprintを使用する場合
```python
# auth.py
from flask import Blueprint

bp = Blueprint('auth', __name__, url_prefix='/auth')

@bp.route('/register', methods=['GET', 'POST'])
def register():
    # ユーザー登録に関する処理
    pass

@bp.route('/login', methods=['GET', 'POST'])
def login():
    # ログインに関する処理
    pass

@bp.route('/logout')
def logout():
    # ログアウトに関する処理
    pass
```

```python
# __init__.py
from flask import Flask

def create_app():
    app = Flask(__name__, instance_relative_config=True)

    from .auth import bp as auth_bp
    app.register_blueprint(auth_bp)

    return app
```

## Blueprintを使う利点

1. モジュール化と整理:

    - Blueprintを使うと、関連するビューや他のコードを1つのコンテナにまとめることができます。これにより、コードベースをより整理され、管理しやすくなります。
    - 異なる機能を異なるBlueprintに分けることで、コードの分離が容易になります。例えば、認証機能、ブログ機能、APIエンドポイントなどをそれぞれ別のBlueprintとして管理できます。

2. 再利用性の向上:

    - Blueprintは再利用可能なモジュールとして設計されています。例えば、認証機能を持つBlueprintを他のプロジェクトで簡単に再利用することができます。

3. URLプレフィックスの設定:

    - BlueprintにURLプレフィックスを設定することで、関連するすべてのURLに共通のプレフィックスを付けることができます。これにより、URLの一貫性が保たれ、コードが読みやすくなります。
    - URLプレフィックスを使うことで、アプリケーションの異なる部分に異なる名前空間を与えることができます。

4. 独立した設定とミドルウェア:

    - Blueprintごとに異なる設定やミドルウェアを適用することができます。例えば、特定のBlueprintにのみ適用される認証ミドルウェアを設定することが可能です。

5. テストの容易さ:

    - Blueprintを使うことで、個別の機能モジュールごとにテストを行うことが容易になります。各Blueprintを独立してテストできるため、テストのメンテナンスがしやすくなります。

## まとめ
Blueprintを使用することで、Flaskアプリケーションのコードをより整理しやすくし、再利用可能なモジュールとして管理できるようになります。単にモジュールをインポートしてビュー関数を登録するよりも、Blueprintを使うことでコードの分離、再利用性、URL管理、設定の柔軟性が向上します。これにより、大規模なアプリケーションや複数の開発者が関与するプロジェクトでも効率的に開発を進めることができます。
疲弊した社畜や大学院生の心を癒やすため，猫と戯れるアプリを作ってみた

# エンジニア業界における猫の必要性とその先行例
エンジニア業界において，猫は非常に重要な存在である．遊んだ心を癒やし，仕事の効率を上げるためには，猫と戯れることが必要不可欠である．

これまでも様々な猫と戯れるためのアプリが開発されてきた．デバッグやコーディングは精神的ダメージの大きい作業である場合が多い点，往々にしてそのような作業は〆切に追われる傾向がある点などから，開発環境と猫を組み合わせた先行例が多いようである．

筆者がざっと探しただけでも，猫アプリやプラグインは以下のものが見つかった．

1. Vimのプラグインとして
   - [どうしてもvimで猫と戯れたい！](https://qiita.com/kuroitu/items/acba18d9551705369af7)
   - [nyancat.vim](https://github.com/kat0h/nyancat.vim)
2. VSCodeのプラグインとして
   - [Bongo Cat Buddy](https://github.com/KrappRamiro/bongocat-vscode-ext)
   - [VSCodeでペットを飼う](https://qiita.com/flowernotfound/items/455a078dbde1d2fc497b)

これらのアプリはプラグインとして提供されているものが多い．しかしながら，これらのアプリはここの開発環境に特化しているため，WordやExcelなどのOfficeやブラウザ上では猫と別れなければいけない．これは非常に残念なことである．

# なければ作ればいい
Windows環境で常に猫がいてくれるようになればいい．必要な要件は以下の通りである．

1. Windows上で動作すること
2. 常に画面上に猫が表示されること
3. 使用者の動作に対しに何らかの応答を示すこと
4. **かわいいこと**

# 作ってみた
上記の要件を満たすWindowsアプリを実際に作ってみた．
使用者のキーボード入力と連動して，ボンゴキャットがタイピングしてくれる．

![bongo_cat.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550865/07c03e79-f68b-1905-e898-78382e42b5dd.gif "Typing Bongo Cat")

# 使用方法
1. [リリースページ](https://github.com/hurokume/Typing-Bongo-Cat/releases/latest)から最新のZIPファイルをダウンロードする．
2. ZIPファイルを解凍する．
3. ```Typing Bongo Cat.exe```を実行する（単一のexeファイルにできなかったので，大量にファイルが存在する）．
![explorer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550865/986d4167-7777-b4bf-0923-b65b0c441e84.png)

# 注意点
- 今のところWindows環境のみで動作する．
- 初回実行時はWindowsセキュリティチェックが走るらしく，15秒ほどかかる場合がある．
[Cryptosystem] 共通鍵暗号方式、公開鍵暗号方式、デジタル署名について

# 早見表
||共通鍵暗号方式|公開鍵暗号方式|デジタル署名|
|:--|:-:|:-:|:-:|
|キー名|共通鍵|公開鍵、秘密鍵|公開鍵、秘密鍵|
|キー所有者|送信者、受信者|受信者|**送信者**|
|使用方法|共通鍵で暗号化、復号|公開鍵で暗号化<br>秘密鍵で復号|秘密鍵で暗号化（署名）<br>公開鍵で復号（検証）|
|実装方式|AES<br>DES|RSA<br>楕円曲線暗号<br>ElGamal||
|n人の通信の<br>必要な鍵数|**n(n-1)/2**|**2n**||


# 参考リンク
- [令和5春38_デジタル証明](https://www.ap-siken.com/kakomon/05_haru/q38.html)
Python `itertools.groupby`でデータをグループ化する方法

## はじめに
Pythonでデータ処理を行う際、同じ値や条件でデータをグループ化することがよくあります。`itertools.groupby`は、このようなグループ化を効率的に行うための強力なツールです。この記事では、`itertools.groupby`の使い方と実践的な例を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/425bb3f2-1d94-39a4-e21a-0ed6a1b0bcb3.png)

## `itertools.groupby`とは

`itertools.groupby`は、Pythonの標準ライブラリ`itertools`に含まれる関数で、イテラブル（リストなど）の連続する要素をグループ化します。グループ化の基準は、キー関数によって決定されます。

## 基本的な使い方

```python
from itertools import groupby

# データ
data = [1, 1, 2, 3, 3, 3, 4, 5, 5]

# グループ化
grouped = groupby(data)

# 結果の表示
for key, group in grouped:
    print(f"{key}: {list(group)}")
```

出力:
```
1: [1, 1]
2: [2]
3: [3, 3, 3]
4: [4]
5: [5, 5]
```

## キー関数を使ったグループ化

より複雑なデータ構造では、キー関数を使ってグループ化の基準を指定できます。

```python
from itertools import groupby

# データ
data = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
    {"name": "Charlie", "age": 25},
    {"name": "David", "age": 30}
]

# 年齢でグループ化
grouped = groupby(data, key=lambda x: x["age"])

# 結果の表示
for key, group in grouped:
    print(f"Age {key}:")
    for item in group:
        print(f"  {item['name']}")
    print()
```

出力:
```
Age 25:
  Alice
  Charlie

Age 30:
  Bob
  David
```

## 注意点

1. `groupby`を使用する前に、データをソートする必要があります。グループ化は連続する要素に対してのみ行われるためです。

2. `group`オブジェクトはイテレータなので、複数回使用する場合は`list()`などでリスト化する必要があります。

## 公式ドキュメント

より詳細な情報や高度な使用方法については、Python公式ドキュメントを参照してください：

- [itertools.groupby()](https://docs.python.org/3/library/itertools.html#itertools.groupby)

公式ドキュメントでは、`groupby()`の詳細な仕様、パラメータ、返り値の説明、そして使用例が提供されています。特に、以下の点に注目すると良いでしょう：

- `key`パラメータの詳細な説明と使用方法
- グループ化の動作に関する詳細な説明
- パフォーマンスに関する考慮事項

また、`itertools`モジュール全体のドキュメントも参考になります：

- [itertools — Functions creating iterators for efficient looping](https://docs.python.org/3/library/itertools.html)

このページでは、`groupby()`以外の便利な関数も紹介されており、データ処理の効率を上げるのに役立ちます。

## まとめ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/08469956-fbaa-5355-605d-b5b0f5b832fd.png)

`itertools.groupby`は、Pythonでデータをグループ化する強力なツールです。適切に使用することで、データ処理の効率を大幅に向上させることができます。ただし、使用前にデータをソートする必要があることと、グループオブジェクトの特性を理解しておくことが重要です。

公式ドキュメントを参照することで、より深い理解と高度な使用方法を学ぶことができます。これらの知識を活用して、より効率的なデータ処理を行ってください！
Node.jsのBufferを使って、画像をbase64のバイナリ形式に変換してHTMLに埋め込む

Puppeteerというライブラリを使ってHTMLからPDFを作成していた時に、画像ファイルが表示されない（読み込まれない）という問題が発生
→ローカルのファイルは読み込めないのでバイナリで埋め込む必要がある、とのことだった

Bufferを使って変換する方法が簡単にできたのでメモ

まず、画像をバイナリに変換する方法
```JS:logic.js
// 画像ファイルを読み込む
//../../assets/image.pngは読み込むファイルのパス
const imageBuffer = fs.readFileSync(path.resolve(__dirname, '../../assets/image.png'));
// BufferをBase64文字列に変換
const base64String = imageBuffer.toString('base64');
```

HTMLの実装
```HTML:template.html
<img src="data:image/png;base64,${binaryImage}" alt="alt text" />
```

バイナリ文字列を置き換える
```JS:logic.js
htmlContent = htmlContent.replace('${binaryImage}', base64String);
```

バイナリに変換する方法は色々あるみたいだけど、このやり方は少ない行数ですっきり書けて良かった
【ChatGPT＋Code Interpreter】で文字列を一文字ずつ出すアニメGIFを作成します。


　どうも、カーブミラーです。

　今回は、文字列を一文字ずつ出すアニメGIFを作成します。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
あります。　あしからず。
:::

　ニュースはないので、
　　さっそく本題です。

　今回は、
　　文字列を一文字ずつ出す
　　　アニメGIFを作成します。

　動画で
　　よく見掛けるテロップ的なものは
　　　できるかな、と思って
　　　　やってみました。

　まずは出来上がりをどうぞ。
![text_animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/6ad01a17-4d22-c1ec-c548-13948c42f0f2.gif)

　Promptがこちら。
```Text:文字列を一文字ずつ出すアニメGIF作成Prompt
CodeInterpreterで、白い正方形（512×512）の中央に、“I am a ChatGPT.”という文章を黒色で、フォントサイズを48で、一文字ずつ出すアニメGIFを作成してください。
コードは不要です。
指示に不明な点があれば質問してください。
```

　では、
　　このPromptの説明をしましょう。

　❶Code Interpreter使用宣言
　❷具体的な作業指示
　　　・白い背景
　　　・フォントサイズ指定
　　　・文章を指定
　　　・アニメGIFの内容指示
　　　・アニメGIF化
　❸コード不要を指示
　　　（コード生成を見たくないので）
　❹指示が不足した場合は質問する

　ここで
　　フォントサイズを
　　　数値で指定していますが、
　　　　これは事前に出来上がった
　　　　　Pythonコードを見て、
　　　　　　反映させました。

　もともとは、
　　“大きくして”だったのです。

　しかし、場合によっては
　　数値で指定しない方が
　　　いいかもしれません。

　文章の長さで
　　ChatGPTさんが
　　　調整してくれますからね。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
Ruby ワンライナー 入門2

## 前置き

### ワンライナー

手元で〜 [Ruby ワンライナー 入門 #Ruby - Qiita](https://qiita.com/atm-snag/items/08f13e591444cbe80fa6#%E3%83%AF%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%8A%E3%83%BC)

## 準備

- たまに使うもの
    - `%q`
        - ワンライナーを書いていると，`'`(シングルクォート) や `"`(ダブルクォート) と戦うことになる．
        - 戦いを回避するのに，`%` 記法を使ったりする．[^quote]
    - `;`
        - 既に使っているが行を区切るのに使う．使わなくてもいい．
    - `Hash.new(0)`
        - 初期値指定．集計するときに使ったりする．
        - `BEGIN{h=Hash.new(0)};k,v=$F;h[k]+=v.to_i;END{h.each{|k,v|puts [k,v].join(" ")}}` みたいな
        - 同一オブジェクトらしいので注意が必要
    - `Hash.new{|h,k|h[k]=[]}`
        - ネストしたデータを作る
    - 条件演算子
        - `&&` `||`
        - `and` `or`
        - `? :` `if then else end`
- パースする
    - JSON
        - `JSON.parse(str)`
    - CSV
        - `CSV.parse(str)`
    - 正規表現
        - `m = /(\d+)/.match(str)`


[^quote]: 戦ってもいい．
例えば，`$ ruby -e 'puts "print a single quote"; puts "'"'"'"; puts "Finished!"'`

## Refs

https://docs.ruby-lang.org/ja/latest/class/JSON.html#M_PARSE

https://docs.ruby-lang.org/ja/latest/class/CSV.html#S_PARSE

https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#cond

https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html#percent

https://docs.ruby-lang.org/ja/latest/class/Hash.html#S_NEW
.gitignoreをコマンドで作成する

本記事では.gitignoreをコマンドで作成する方法について説明する．githubなどのリモート上でgitignoreを作成することはできるが，コマンドを用いて.gitignoreを作成することができる．ローカルリポジトリを作成し，リモートリポジトリと紐付ける際に使おう．

# ローカルリポジトリにgitignoreを追加する
```bash
curl -L http://www.gitignore.io/api/<作成したいgitignoreテンプレート> > .gitignore
```
例えばunityの.gitignoreを作成したい際は，
```bash
curl -L http://www.gitignore.io/api/unity > .gitignore
```
PythonとVisualStudioCodeの.gitignoreを作成したい際は，
```
curl -L http://www.gitignore.io/api/python,visualstudiocode > .gitignore
```
このコマンドを実行するとローカル上に.gitignoreを作成できる．


# リモートリポジトリ作成時に.gitignoreを作成する

:::note warn
githubCLIのインストールが入っていない人はインストールすること
```
brew install gh 
```
:::

## githubにログインする
```
gh auth login 
```
`GitHub.com`か`GitHub Enterprise Server`かを選択する．個人利用なら`GitHub.com`を選択すれば良い，
```
? What account do you want to log into?  [Use arrows to move, type to filter]
> GitHub.com
  GitHub Enterprise Server
```

`HTTPS`か`SSH`を選択する
```
? What is your preferred protocol for Git operations on this host?  [Use arrows to move, type to filter]
> HTTPS
  SSH
```
`Y`と入力してEnter
```
? Authenticate Git with your GitHub credentials? (Y/n)
```
`Login with a web browser`で良いと思う．ブラウザでgithubへログインすることになる．
```
? How would you like to authenticate GitHub CLI?  [Use arrows to move, type to filter]
> Login with a web browser
  Paste an authentication token
```
その後，以下のように表示されるのでone-time codeを控えておく．

:::note info
0000-0000は英数字で表示され，ユーザ，タイミングによって異なる値である．
:::

```
! First copy your one-time code: 0000-0000
Press Enter to open github.com in your browser...
```
web上でone-time codeを入力し，githubにログインすると以下のように表示される．

```
✓ Authentication complete.
- gh config set -h github.com git_protocol https
✓ Configured git protocol
✓ Logged in as <githubアカウント名>
```

## リモートリポジトリの作成（ここで.gitignoreを作成する）
このコマンドでリモートに新しくgitignoreを追加した状態でリモートリポジトリを作成する．
```md:プライベートリポジトリなら
gh repo create <リモートリポジトリ名> --private --gitignore <作成したいgitignoreテンプレート>
```
```md:パブリックリポジトリなら
gh repo create <リモートリポジトリ名> --public --gitignore <作成したいgitignoreテンプレート>
```

```md:Unityのgitignoreを追加したい
gh repo create <リモートリポジトリ名> --private --gitignore Unity
```
:::note warn
これだと1つのテンプレートしかできないので注意．**2つ以上**のテンプレートを組み合わせてgitignoreを作成できない
:::

:::note info
自分のGithubアカウントに紐付いた組織アカウントにリモートリポジトリを作成するなら
```md:プライベートリポジトリなら
gh repo create <組織アカウント名>/<リモートリポジトリ名> --private --gitignore <作成したいgitignoreテンプレート>
```
:::

この時点でgithubにアクセスすると自分のリポジトリに作成したものが反映されているはずである．

この先,ローカリリポジトリとリモートリポジトリの関連付けの方法については以下の記事から

https://qiita.com/JavaLangRuntimeException/items/cb1c4372d03cedc875b2#ローカリリポジトリとリモートリポジトリの関連付け

# `おまけ`　github.com上のリモートリポジトリにコマンドでアクセスする方法
## githubCLIにログインしている場合
```bash
gh browse
```

## githubCLIにログインしていない場合
以下のコマンドを実行するとローカルリポジトリに結びついたリモートリポジトリにアクセスできる．
**Macでは**
```bash
open $(git remote get-url origin)
```
**Windowsでは（PowerShellで）**
```powershell
start (git remote get-url origin)
```
結局 QuickSightでグラフを表示する際に、SPICEとAthenaどっちが安く表示できるのか問題について

初めまして、メグです。

今回はタイトルにもある通り、SPICEとAthenaでのDirectQueryのどちらが安く収まるかについて記載していきます。

## 各サービスの料金体系について
### SPICE
SPICEはQuickSightのインメモリです。
料金体系は、保存しているデータ量に応じて毎月課金が発生します。

【金額】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714038/dd9bc807-c92a-25b5-83ee-5545b3f7dc79.png)

例)
10GBのデータを格納している場合の金額

``` math
\begin{align}
10(GB)　 \times　0.38(USD/GB) = 3.8(USD)
\end{align}
```

### Athena(SQLクエリ)
Athneaの課金額は、クエリを叩いた際にスキャンされるデータ量に応じて課金額が決まります。

そのためデータ量の大きいテーブルに対して何度もクエリを叩いていると、それだけで料金がかさばります。

【金額】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714038/dc4f42cf-5716-86c0-bed7-69cedbb8c602.png)

例)
1回のクエリで10GBのデータをスキャンした際の金額

``` math
\begin{align}
10(GB)　 \times　\frac{5}{1024}(USD/GB) = 0.049(USD)
\end{align}
```

## 比較
各料金の直接的な比較ができないため、以下の条件で比較をします。

SPICE料金は、10GBのデータを格納した際の料金を計算します。
Athenaでは、1回あたりのクエリのデータスキャン量を 10GBとして料金を計算します。

SPICEの料金に、Athneaのクエリを何回叩けば届くのかを導きます。

``` math
\begin{align}
クエリの上限 = \frac{SPICEのデータ量(GB) \times0.38(USD/GB)}{クエリあたりのデータスキャン量\times\frac{5}{1024}(USD/GB)}

\end{align}
```
``` math
\begin{align}
= \frac{10(GB)　 \times　0.38(USD/GB)}{10(GB)　 \times　\frac{5}{1024}(USD/GB)}=77クエリ
\end{align}
```

今回の計算上、77回クエリを叩けば SPICEの料金に届くことがわかりました。
つまり、77回クエリを叩かないのであれば Athenaのほうがお得になるという結果になります。

# 注意
今回の計算では、以下のようなことを考慮しています。
実際にご自身の環境で試す際は、ご注意ください。

##### １．SPICEは格納するデータの形式にもよりますが、基本格納する前のデータ量よりも、SPICEで保持するデータ量の方が大きくなります。
##### ２．作成者アカウントがある場合は、SPICEはデフォルトで 10GB付与されます。
##### ３．Athenaを使用する場合は、データ圧縮・列指向・パーティションを施すことで、1回あたりのスキャンされるデータ量を最小10MBまで抑えることができます。


# 自己紹介
初めまして、メグです。(@megggguguuuuuuu)

高専を卒業後、新卒で今の会社に入社をしました。
今年で3年目突入になります。

現在は、AWS関連のメインの業務に参画しているため、
AWSの勉強を行っております。

AWS資格を現在 CLF,SAA,SOA を取得しています。
(DVAについては、12月ごろ受験予定)

AWS資格 12冠することが目標です。
同じくAWS 資格を目指す方は、お互いに刺激しあいながら資格取得に向けて頑張りましょう！

# 宣伝
毎週の土日に、僕が入社している会社のオフィス(池袋)にて「もくもく会」をしています。
ぜひご興味がある方がいましたらご参加ください！！！

https://mokumoku-teikoku.connpass.com/
Visual Studio Code (VS Code) で GitHub に変更点をコミットする方法

### VS Code でのステージングとコミットの手順

1. **VS Code を開く**

   - **手順**: VS Code を開きます。プロジェクトのフォルダーを開くためには、メニューから「ファイル」 > 「フォルダーを開く」を選んで、作業したいプロジェクトのフォルダーを選びます。
   - **目的**: プロジェクトのファイルにアクセスできるようにします。

2. **変更点の確認**

   - **手順**: 左側のサイドバーにある「ソース管理」アイコン（分岐する線が描かれているアイコン）をクリックします。
   - **目的**: 「ソース管理」ビューで、どのファイルが変更されたのかを確認できます。ここには変更されたファイルが一覧で表示され、変更内容も見ることができます。

3. **ファイルのステージング**

   - **ステージングの意味**: ステージングは、コミットに含めたい変更を選ぶ作業です。これは「準備完了」のようなものです。
   - **手順**:
     - 個別のファイルをステージングするには、そのファイル名の隣にある「＋」ボタンをクリックします。これでそのファイルが「ステージされた変更」セクションに移動します。
     - すべての変更を一度にステージングしたい場合は、リストの上にある「すべての変更をステージ」ボタン（全体に表示される「＋」アイコン）をクリックします。
   - **目的**: ステージングされたファイルは「ステージされた変更」セクションに表示され、これでこれから行うコミットに含まれる準備が整います。

4. **ステージングの解除**

   - **手順**: ステージングしたくないファイルがある場合、そのファイルの隣にある「－」ボタンをクリックします。
   - **目的**: ステージングから外れたファイルは「変更」セクションに戻ります。つまり、コミットから除外されます。

5. **コミットメッセージの入力**

   - **手順**: 「ソース管理」ビューの上部にあるテキストボックスに、コミットの説明を書きます。例えば、「バグ修正」や「新しい機能の追加」などです。
   - **目的**: このメッセージは、コミットの内容を説明するためのもので、後で変更内容を振り返るときに役立ちます。

6. **コミットの実行**

   - **手順**: メッセージを入力したら、テキストボックスの隣にある「チェックマーク」ボタンをクリックします。
   - **目的**: ステージされた変更がローカルリポジトリに保存され、コミットとして記録されます。これで変更が確定し、バージョン管理が行われます。

これで、VS Code でのステージングとコミットの基本的な操作が完了です。簡単に言うと、ステージングは「保存する準備をする」作業で、コミットは「保存する」作業です。
GASでGoogle Formsの「回答に応じてセクションを移動」を指定

# 概要
Google Apps Script(GAS)を用いてGoogleForms内における「回答に応じてセクションを移動」を指定できます．
該当の文献・実装例が少ないので備忘録として残しておきます．

# 方法
```js
const target_item_num = 2; //フォーム全体の中で，設定したい質問が何番目か
const form = FormApp.openByUrl("フォームのURL");
const form_items = form.getItems();

const section_2 = form.getItems(FormApp.ItemType.PAGE_BREAK)[0].asPageBreakItem(), // 2つ目のセクション(PAGE_BREAKで取得すると，セクション2=[0], セクション3=[1])

let choices = [];  //選択肢一覧
choices.push(form_items[target_item_num].asListItem().createChoice("セクション2に移動する選択肢", section_2)); //対象の質問に対する選択肢を追加
form_items[target_item_num].asListItem().setChoices(choices);  //作成した選択肢をフォームに反映
```
1. `フォームのURL`と`target_item_num`, `セクション2に移動する選択肢`を編集してください．
2. `target_item_num`はフォーム内での質問のインデックス番号です．（下の画像だと「金額」=[0]）
![Screenshot 2024-08-05 at 11.13.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989725/3253be03-2e97-04ce-2ee4-384c23a2cb1c.png)
インデックス番号が不明な場合は，以下のコードで番号とタイトル一覧を確認できます．
    ```js
    function show_items(){
        const form = FormApp.openByUrl("フォームのURL");
        const form_items = form.getItems();
        let i = 0;
        form_items.forEach((item)=>{
                console.log(`${i++}: ${item.getTitle()}`)
            }
        )
    }
    ```

# 補足
予測変換やWeb検索，ChatGPTの回答では`createChoice("chice title", GO_TO_PAGE)`という提案がされるかもしれません．
しかし，[GoogleForms APIのドキュメント](https://developers.google.com/apps-script/reference/forms/multiple-choice-item?hl=ja#createchoicevalue,-navigationitem)をよく見ると，特定のセクションに移動するには第二引数に`PageBreakItem`型を指定する必要があります．
Ubuntuの開発環境構築

EC2 の Ubuntu で新たに自分用の開発環境を構築するときのメモ

# zsh

## zsh インストール

```sh
sudo apt install zsh
chsh -s $(which zsh)
```

## oh-my-zsh インストール

https://ohmyz.sh/#install


```sh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

テーマは risto に変更すｒ

```sh
sed -i 's/robbyrussell/risto/' ~/.zshrc
```

### zsh-completions プラグインをインストール

https://github.com/zsh-users/zsh-completions

```sh
git clone https://github.com/zsh-users/zsh-completions ${ZSH_CUSTOM:-${ZSH:-~/.oh-my-zsh}/custom}/plugins/zsh-completions
```

```~/.zshrc
fpath+=${ZSH_CUSTOM:-${ZSH:-~/.oh-my-zsh}/custom}/plugins/zsh-completions/src
```

### asdf をインストール

https://asdf-vm.com/ja-jp/guide/getting-started.html

保存先を作成
```sh
mkdir ~/.asdf/bin
```

バージョンはそのときどきによって変わるので https://github.com/asdf-vm/asdf/releases を確認しておく
```sh
wget -qO- https://github.com/asdf-vm/asdf/releases/download/v0.16.7/asdf-v0.16.7-linux-amd64.tar.gz | tar -xzf - -C ~/.asdf/bin
```

```~/.zshrc
export PATH="${HOME}/.asdf/bin:${HOME}/.asdf/shims:$PATH"
```

oh-my-zsh の asdf プラグインも有効にしておく

```~/.zshrc
plugins=(git asdf)
```

~/.asdfrc に以下を追加
```:.asdfrc
legacy_version_file = yes
```

# 開発用パッケージをインストール

```sh
sudo apt install build-essential libz-dev libffi-dev libssl-dev libyaml-dev
```

# Docker をインストール

https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script

```sh
curl -fsSL https://test.docker.com -o test-docker.sh
sudo sh test-docker.sh
```
権限の書き換え
```sh
sudo chmod 666 /var/run/docker.sock
```