OmniAICreator/Qiita-1.07M huggingface dataset:
クラスの継承、インターフェース、抽象クラス（Java Silver勉強）

# 最初に
この記事は、以下の書籍を通じてJava silverの合格に向けて自分が学んだ内容を体系的にアウトプットする記事である。（目指せ年始合格！）
[徹底攻略Java SE 11 Silver問題集[1Z0-815]対応]()

# 勉強記録
## クラスの継承、インターフェース、抽象クラス
### 継承

- 継承していても引き継げないもの
    - コンストラクタ
    - privateなフィールドやメソッド
- クラスの多重継承禁止
- 継承関係にある二つのクラスで同名のフィールドがある場合
    - フィールドを参照した場合は、インスタンスの型で宣言された方を使用
    - メソッドを呼び出した場合は、メソッド内の指示に従う
    - 参考）https://qiita.com/Shiho_anyplus/items/eabc380fcc8719ee4871
- 継承関係にあるクラスのコンストラクタの挙動
    - スーパークラスのコンストラクタ呼び出しの後に、サブクラスのコンストラクタが呼び出しされる
    - スーパークラスのコンストラクタ呼び出しの記述がない場合、コンパイラによって、サブクラスのコンストラクタの1行目にsuper()が自動で追加される

### インターフェース

- 多重実現、多重継承ともにOK
- メソッド
    - アクセス修飾子は、publicのみ（記述しなくてもOK）
    - 基本的に、処理の中身を一切記述できない（defalutメソッドは除く）
    
    ```clike
    public interface Sample{
    	// 以下のように定義する（publicはなくても良い）
    	public void hello();
    
    	//　以下は、コンパイルエラーとなる（処理なしという中身を持つと解釈されるため）
    	public void hello(){}
    }
    ```
    
    - 抽象メソッドは、インターフェースを実現したクラスが、必ず実装しなければならない（defalutメソッドは除く）
- defaultメソッド
    - インターフェースに処理の中身を記述できる
    - インターフェースを実現したクラスが、実装する必要もない
    
    ```clike
    public interface Sample{
    	defalt void print(int num){
    		System.out.println(num);
    	}
    }
    ```
    
    - java.lang.Objectクラスに定義されているメソッドは、defautメソッドとしてオーバーライドできない
    - defaultメソッドをオーバーライドしたメソッドから、元のdefaultメソッドを呼び出す場合
    
    ```clike
    インターフェース名.super.メソッド名();
    // 正し、直接実現したクラスのみ呼び出し可能
    // 2つ以上の実現や継承の階層を跨いでの呼び出しは不可
    ```
    
- フィールド
    - 定数のみ（finalを必ずつける）
    - インスタンスを生成しなくても使える（staticを必ずつける）
    

### オーバーライド

- 3つのルール
    - シグニチャ（メソッド名+引数）が同じであること
    - 戻り値型は、同じか、サブクラス型であること
    - アクセス修飾子は、同じかより緩いものを指定すること

### 型変換

- スーパークラス型をサブクラス型に、インターフェース型を実装クラス型に変換する際は、明示的にキャスト式を記述する必要がある（アップキャストは明示不要だが、ダウンキャストは明示必要）
    
    ```clike
    public class A{
    	//処理
    }
    
    public class B extends A{
    	//処理
    }
    
    public static void main(String[] args){
    	//アップキャストは明示不要
    	A a = new B();
    
    	//ダウンキャストは明示必要
    	B bOk = (B)a;
    
    	//以下はNG
    	B bNg = a;
    }
    ```
    
- 型同士に互換性がない場合の型変換は、コンパイルエラーではなく、例外となる
    
    ```clike
    public class A{
    	public void print(){
    		System.out.println("A");
    	}
    }
    
    public class B extends A{
    	public void print(){
    		System.out.println("B");
    	}
    }
    
    public static void main(String[] args){
    	A a = new A();
    	//キャストにより、互換性の保証をしているため、コンパイルエラーとはならない
    	B b = (B)a;	
    	//しかし、aは、Aのインスタンスのため、AとBの処理内容の差分を含んでおらず、Bでオーバーライドしたメソッドを実行できない
    	b.hello();
    }
    ```
    

## 感想

- 抽象クラスと実現、Java silverの問題を解く分には問題なさそうなくらいの理解度だが、自分で0からインターフェースや抽象クラスを設計するとなるとまだ不安が残る理解度というのが正直なところ。思えば、過去2年で自分が携わった開発案件は、すでにクラス設計が固まっていたサービスだったので、なぜ抽象クラスやインターフェースでこの処理を扱っているかというところに着目せずにcodingしていた気がする。自分で0から作り上げる経験を積む必要があるなと感じた。
ts-expect-error

メモ書きです。

## 例外のテストを書きたい
```ts
const sum = (a: number, b: number) => a + b
```

今まで
```ts: sum.test.ts
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore-next-line
sum('1', 2)
```

最近知った
```ts: sum.test.ts
// @ts-expect-error: 例外チェック
sum('1', 2)
```

そんなんあったんか…
Wp Go Maps プラグインの日本語化について

### はじめに
 この解説は、バージョン 9.0.28をもとにしております。
 　https://ja.wordpress.org/plugins/wp-google-maps/
　Google map のプラグインとして非常に使いやすい「Wp Go Maps」ですが、翻訳ファイルをダウンロードしてインストールしても反映されません。


### アップロード先
　反映させるには、通常の翻訳ファイルをアップロードする場所にアップロードしても反映されないためです。
アップロードは、下記の場所で行ってください。

wp-content＞plugins＞wp-google-maps＞languages



### ダウンロードサイト
　翻訳ファイルは、下記よりダウンロードができます。
https://translate.wordpress.org/projects/wp-plugins/wp-google-maps/language-packs/

### 最新版のダウンロード先
　まだ承認されていない翻訳ファイルは下記のページの下部から「po」と「mo」ファイルをダウンロードして上部にアップロードを行ってください。
https://translate.wordpress.org/projects/wp-plugins/wp-google-maps/dev/ja/default/

　更に使いやすくするためにgoogle翻訳を利用して翻訳作業を行い翻訳ファイルに反映する作業も行っています。
どなたか翻訳内容が間違ってないか確認よろしくお願いします。
SharePointで古くなった記事を自動削除

## はじめに
SharePointで社内ポータルを開設しようと検討している方、一定数いるのかなと思います。ですが、SharePoint関連の技術ブログってあまり豊富じゃなく、ググってもそんなにヒットしないんですよね。
今回はSharePointの掲示板機能で、古くなった記事を自動で削除する設定を紹介したいと思います。

### 参考にしたサイト
https://www.sharepoint.jp.net/2014/10/20/%E5%8F%A4%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E8%87%AA%E5%8B%95%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF/

#### 具体的な設定手順
SharePointのチームサイト右上の歯車マークから、「リストの設定」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/109b8232-2ff9-1069-2285-a6ec38e3f05e.png)

「情報管理ポリシーの設定」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/aef46ff2-92c9-6bd2-2e82-3b727d689961.png)

コンテンツタイプの「お知らせ」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/30fb5566-e9f8-75c7-554e-47a925f8477f.png)

「保持を有効にする」にチェックを入れ、「保持ステージを追加する」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/0046dc62-e4ac-41b4-cec5-9e5a11d96f74.png)

イベントと処理をそれぞれ設定します。
【例】
期間：有効期限+1日
処理：ごみ箱に移動
→有効期限を1日過ぎたら、アイテムがごみ箱に自動で移動される設定になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/2c8265d3-9754-8826-6fe2-6cb96b64d8d6.png)

OKで画面を閉じます。

情報管理ポリシー設定画面にて、カスタムポリシーが定義済みになっていれば設定完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1980545/8bfadb8f-bcdb-ca07-3c27-0d7388c43bff.png)

以上！

#### 注意点
上述した参考サイトにも記載があるのですが、情報管理ポリシーは週に1度実行される仕組みのようです。
つまり、有効期限+1日でごみ箱に移動させる設定にしていても、実際は1日後ではなく、2～8日後の間に削除処理が行われます。実行頻度の変更も可能のようですが、今回はそこまでご紹介いたしません。悪しからず。

## おわりに
設定手順は簡単なのですが、独力で設定画面に辿り着くのがなかなか難しいかなと感じました。みなさんの一助となれば幸いです！
札幌市のOpen Dataにアクセスしてみませんか？

## DATA-SMART CITY SAPPORO

>一般財団法人さっぽろ産業振興財団は、札幌圏地域データ活用推進機構（SARD）の理念と機能を継承し、市民生活の利便性向上や、新たなサービス創出による経済の活性化、行政保有データの活用が容易になることによる行政の信頼性や透明性の向上に資するため、圏域で発生し官民が保有する様々なデータ（いわゆる「官民データ」）を協調して利活用できる環境を整備し、官民がデータ利活用を促進する「データの地産地消」の実現に向け事業を推進しています。
引用：https://data.pf-sapporo.jp/about_site/

`DATA-SMART CITY SAPPORO`という[プラットフォーム](https://data.pf-sapporo.jp/)から、官民データにアクセスできるとのことなので、データアクセスを行う`NPM package`を作成してみました。

## 開発手順

手順自体は、以前公開した[投稿](https://qiita.com/i2i3i/items/3938aacc87ac66a119f5)に載せているので、もし気になる方はそちらを確認してみてください。

[コード](#ソースコード)も公開していますので、必要なPackageや設定も確認いただけます。

## 使い方

- Install

```bash:shell
npm i @i2i3i/open-data-in-sapporo
```

- アクセス可能情報一覧

[open-data.json](https://github.com/HIppei/open-data-in-sapporo/blob/main/open-data.json)に、アクセス可能なデータ一覧を載せています。

以下が`１　来札観光客数の推移`を取得する際に利用する情報です。

`group:statistics_sapporo`と`resourceId:821c83f6-492b-44db-bbde-fca9d2774645`を`open-data.json`から参照し、`odisap`というファンクションに渡します。

```json:open-data.json
 "statistics_sapporo": {
    "821c83f6-492b-44db-bbde-fca9d2774645": {
      "title": "１　来札観光客数の推移",
      "param": { "年　度": "", "観光客数（千人）": 0, "前年度比（％）": "" }
    },
```

```typescript:example.ts
import odisap from '@i2i3i/open-data-in-sapporo';

const func1 = async () => {
  const res = await odisap(
    'statistics_sapporo',
    '821c83f6-492b-44db-bbde-fca9d2774645'
  );

  console.log('result', res.result);
  console.log('records', res.result.records);
};

await func1();
```

パラメータによる絞り込みや、データ数制限などの例は、[NPM Packageページ](https://www.npmjs.com/package/@i2i3i/open-data-in-sapporo)で確認いただけます。



## ソースコード

[GitHub](https://github.com/HIppei/open-data-in-sapporo/tree/main)に公開済みです。

## データは公開されているけれど…

`DATA-SMART CITY SAPPORO`という取り組み自体は素晴らしいものだと思います。公的データという裏付けにもなるので様々な場面で役に立ちそうな気がします。

**ただ、以下の点が気になりました。**
一応、運営元に質問/バグ報告/要望としてメールしています。（2023/12/24くらいに送って返答なしですが、、）

- API Endpoint
API Endpointからデータアクセスを試すには、[API利用方法](https://data.pf-sapporo.jp/apiuse/)に記載されている方法ではうまくいかず、[CKAN](https://docs.ckan.org/en/latest/maintaining/datastore.html#the-data-api)に記載されている方法と、実際のNetworkリクエスト、レスポンスを確認する必要がありました。この辺がもっと分かりやすいと良かったです。

<br>

- アクセス情報一覧
情報が散らばっているので、一覧形式でアクセス可能な情報とパラメーターが見れると尚良かったです。今回は[crawler](https://www.npmjs.com/package/crawler)を利用して、機械的に情報を集めて、`open-data.json`に落とし込んでいます。

<br>

- サイト内の`よくあるご質問`や`お問い合わせ`
バグっているので、このサイト自体の信頼性を疑いました。

## 他の自治体も

デジタル庁が公開している[情報](https://www.digital.go.jp/resources/data_local_governments)から確認できるようです。

ちなみに私も初めて知ったのですが、CKANというデータマネジメントシステムがあるんですね。面白そうなので、ドキュメントを確認中です。
【Docker】docker composeを使ってコンテナ構築、管理をしてみる

最近docker composeを利用してコンテナ構築をしたり、コンテナ操作をしたりするので、まとめます。

# Docker composeとは
Docker composeとは簡単に複数のコンテナ操作を行うことができるツールです。
Docker composeを用いてコンテナ操作を行うには、docker-compose.yamlを作成します。
コンテナ自体の定義はDockerfileに記載しますが、そのコンテナをどういった設定で起動するかなどはdocker-compose.yamlファイルに記載します。

※本記事の趣旨とはズレるため、ファイルの例は割愛

# コンテナのビルド
コンテナのビルドとはコンテナイメージを作成するという意味です。
イメージは必ず一意に作成され、そのイメージからコンテナを作成すれば、必ず同じ状態のコンテナであることが保証できます。

以下のコマンドにてコンテナのビルドが可能です。
```
cd [docker-compose.yamlが存在するパス]
docker compose build
```

コンテナイメージを確認は以下のコマンドで可能です。
```
docker images
```

# コンテナの起動
ビルドによって作成されたイメージを利用してコンテナ起動ができます。
```
docker compose run [コンテナ名]
```

# ビルドと起動を一発でやるコマンド
上記のbuildとrunを利用するケースは以下を想定しています。
・dockerイメージを作成し、dockerリポジトリにpush
・コンテナを起動したい環境にてリポジトリからイメージをpull
・runコマンド実行

一方で、リポジトリを経由せず直接docker-compose.yamlから起動を行いたい場合があると思います。
この場合はイメージ作成、コンテナ起動を一発で行うコマンドを利用できます。
```
docker compose up --build
```
※--buildはオプションであり、キャッシュを利用せずにイメージの作成からやってくれるものです。

# コンテナの状態を確認
コンテナの状態を確認するコマンドは以下です。
```
docker ps -a
```
起動しているコンテナが一覧となって表示されます。

# コンテナにログイン
コンテナの中身を確認したい場合、コンテナにログインする必要があると思います。
その場合は、以下のコマンドを利用します。
```
docker exec -it [コンテナID] /bin/bash
```
コンテナにログインし、操作ができます。

# コンテナからホストにファイルをコピー
コンテナにあるログファイルなどをホストにコピーしたい場合があると思います。
その場合は以下のコマンドが利用できます。
```
docker cp [コンテナID]:[コピー元のファイルパス] [コピー先のファイルパス]
```
上記のようにすると簡単にコピーができます。

# ホストからコンテナにファイルをコピー
上記の逆です。
```
docker cp [コピー元のファイルパス] [コンテナID]:[コピー先のファイルパス]
```

# コンテナの停止、削除
コンテナを停止する場合は以下のコマンドを利用します。
```
docker stop [コンテナID]
```

コンテナ自体の削除をしたい場合は以下のコマンドを利用します。
ちなみに、起動しているコンテナは削除できないので、コンテナ停止→コンテナ削除の順に実行する必要があります。
```
docker rm [コンテナID]
```

最後にコンテナイメージの削除をします。
コンテナイメージはコンテナのビルドを行うたびに生成されるので、放置しておくとストレージの圧迫の原因になります。
私の場合、開発時やテスト時に定期的にイメージを確認し、不要なものは削除するような運用が必要でした。
以下のコマンドが利用できます。
```
docker images // コンテナイメージ確認
docker rmi [コンテナイメージID]

docker rmi [コンテナイメージID]　[コンテナイメージID]　[コンテナイメージID]
// 同時に複数の削除も可能

sudo docker image prune
// 古いimageを一回で消すことも可能
```
※rmと似てますが、remove imageということでrmi（と思ってる）

私が開発でdocker系を利用した際は、基本的に上記のコマンドを利用することが多かったです。
良かったら参考にしてみてください。

以上。
タイ語における単文字トークナイザとタイ文字クラスターの間で

Thodsaporn Chay-intr, Hidetaka Kamigaito, Manabu Okumura『[Character-Based Thai Word Segmentation with Multiple Attentions](https://doi.org/10.5715/jnlp.30.372)』を読んでいて、Character-Basedの意味するところに多少悩んでしまった。というのも、この論文では、いわゆる単文字トークナイザを想定していて、母音や声調記号すら1文字とみなして切ってしまうようなのだ。Figure 1の例文「มี ๓ ความหมาย」をpython3で見てみよう。

```
>>> sample="มี ๓ ความหมาย"
>>> print([c for c in sample if not c.isspace()])
['ม', 'ี', '๓', 'ค', 'ว', 'า', 'ม', 'ห', 'ม', 'า', 'ย']
```

「มี」が2文字に別れていて、非常に気持ちが悪い。このあたりに対して[Unicode Standard Annex #29](https://www.unicode.org/reports/tr29/)では、書記素クラスター(grapheme cluster)というのが規定されていて、もう少し普通に切ってくれる。[pyuegc](https://github.com/mlodewijck/pyuegc)の助けを借りてみよう。

```
>>> import pyuegc
>>> print([c for c in pyuegc.EGC(sample) if not c.isspace()])
['มี', '๓', 'ค', 'ว', 'า', 'ม', 'ห', 'ม', 'า', 'ย']
```

あるいは、タイ語固有のアイデアとしては、[タイ文字クラスター](https://doi.org/10.1145/355214.355225)(คลัสเตอร์อักษรไทย)というのが[30年以上前に提案](https://www.researchgate.net/publication/243659316)されていて、Hugging Face / tokenizersだと、[pre_tokenizers](https://huggingface.co/docs/tokenizers/api/pre-tokenizers)で簡単に実装できる。ちょっと見てみよう。

```
>>> from tokenizers import pre_tokenizers as pre,Regex
>>> tcc=pre.Sequence([pre.Whitespace(),pre.Split(Regex("[\u0e40-\u0e44]?[\u0e01-\u0e2e][\u0e30-\u0e3a\u0e45\u0e47-\u0e4e]*|."),"isolated")])
>>> print(tcc.pre_tokenize_str(sample))
[('มี', (0, 2)), ('๓', (3, 4)), ('ค', (5, 6)), ('วา', (6, 8)), ('ม', (8, 9)), ('ห', (9, 10)), ('มา', (10, 12)), ('ย', (12, 13))]
```

この論文『Character-Based Thai Word Segmentation with Multiple Attentions』は、タイ文字クラスターには言及しているが、書記素クラスターには言及がない。結果として、タイ文字クラスターの要約ベクトルを、単文字トークナイザから頑張ってアテンション機構で組む、という大技になっている。まあ、それはそれで面白いのだけど、1文あたりのトークン数が長くなっちゃうので大変だなぁ。
Rust をwasm バインドする時に、thread_rnd: this target is not supported

## 概要

Rust をWasm化してJSから呼ぼうとしていた時のことでした。

基本的には

https://developer.mozilla.org/ja/docs/WebAssembly/Rust_to_Wasm


こちらのチュートリアルを追っていたのですが、
バインドしたいライブラリの中でrand が使われており

```cargo.toml
[dependencies]
rand = "0.7.3"

```

```
thread_rng: getrandom: this target is not supported
```

と言うようなエラーが、JSのランタイムで起きていました。


## 解決策

バインドするライブラリの依存関係に

```cargo.toml
[dependencies]
getrandom = { version = "0.2.2", features = ["js"] }
rand = "0.7.3"
```

とし、

```rust
let mut rng = rand::thread_rng();
rng.gen_range(0, 2)
```

のように生成していた乱数を、`getRandom`を用いて生成するように変更します。
具体的には、


```rust
    // Define the range
    let lower_bound = 0;
    let upper_bound = 2;
    // Calculate the size of the random byte slice needed
    let range_size = upper_bound - lower_bound + 1;

    let mut random_bytes = [0u8; 4];

    getrandom(&mut random_bytes).expect("Failed to generate random bytes");

```

のようにして生成します。
これでWASM化すると、
JSからWASM経由で乱数生成を実行することができました。



以上。
WSL2でcuda12+cuDNN環境構築(Dockerなし)

# はじめに
WSL2のUbuntu 22.04,Ubuntu 24.04で環境構築した結果いけたので多分大丈夫
他のUbutnuやMintなどにインストールする場合は適宜URLを変更してください

# 環境構築

### とりあえずアップデート

```bash
sudo apt update && sudo apt full-upgrade -y
```

## cudaインストール

以下のURLで対応したOSのインストラクションがあるのでWSLじゃない人は参考にすると良い。

[CUDA Toolkit 12.3 Update 2 Downloads](https://developer.nvidia.com/cuda-downloads)

[cuDNN Download](https://developer.nvidia.com/rdp/cudnn-download)

以下のシェルスクリプトを実行してtest pass!!みたいなのが出たら成功

```shell
#!/bin/bash

# cuda12

sudo apt update && sudo apt full-upgrade -y

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin

sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600

wget https://developer.download.nvidia.com/compute/cuda/12.5.1/local_installers/cuda-repo-wsl-ubuntu-12-5-local_12.5.1-1_amd64.deb

sudo dpkg -i cuda-repo-wsl-ubuntu-12-5-local_12.5.1-1_amd64.deb

sudo cp /var/cuda-repo-wsl-ubuntu-12-5-local/cuda-*-keyring.gpg /usr/share/keyrings/

sudo apt-get update

sudo apt-get -y install cuda-toolkit-12-5

# cuDNN

wget https://developer.download.nvidia.com/compute/cudnn/9.2.1/local_installers/cudnn-local-repo-ubuntu2204-9.2.1_1.0-1_amd64.deb

sudo dpkg -i cudnn-local-repo-ubuntu2204-9.2.1_1.0-1_amd64.deb

sudo cp /var/cudnn-local-repo-ubuntu2204-9.2.1/cudnn-*-keyring.gpg /usr/share/keyrings/

sudo apt-get update

sudo apt-get -y install cudnn

sudo apt-get -y install cudnn-cuda-12

# test

sudo apt install libcudnn9-cuda-12 libcudnn9-dev-cuda-12 libcudnn9-samples -y

sudo apt install -y libfreeimage3 libfreeimage-dev

cp -r /usr/src/cudnn_samples_v9/ ~/

cd cudnn_samples_v9/mnistCUDNN/

make clean && make 

./mnistCUDNN

```
何も考えず（.ipynb）jupyter notebookが使いたい時に使うコピペ集【Window・ubuntu・docker】

# これは？

~~今年から社内勉強会しようって息巻いているけど、Pandasが～機械学習が～いう前にjupyterの環境作ってもらわにゃいかんかった…~~

ローカル環境のセットアップが手間　&&　やってと言うにも簡潔な手順がなかったため作成

colabで良ければそれが一番簡単なのは間違いない

## windows 

実はほぼコマンドラインで実行可能

~~~bat
@REM 公式からインストーラーをDL
curl -o python-3.11.exe https://www.python.org/ftp/python/3.11.7/python-3.11.7-amd64.exe

@REM コマンドラインでインストーラーを実行
@REM https://docs.python.org/ja/3/using/windows.html#installing-without-ui
echo ユーザーアカウント制御が開きますので「はい」（許可）をクリック
start /wait python-3.11.exe /passive InstallAllUsers=1 PrependPath=1 Include_test=0

@REM pathの一時設定
path C:\Program Files\Python311\Scripts\;C:\Program Files\Python311\;%PATH%

@REM jupyterのインストール
@REM https://jupyter.org/install
pip install notebook

@REM jupyterの起動。ブラウザが開く
python -m notebook
~~~

## ubuntu

aptで入る（pythonはデフォで入っている）

~~~bash
sudo apt update
sudo apt install -y python3 python3-venv python3-pip
pip install notebook
python3 -m notebook
~~~

23系ではパッケージ管理が変わっている様子。
グローバルなpip installで警告が出る模様。
APTでインストールする。

~~~bash
sudo apt update
sudo apt install -y \
    python3 \
    python3-venv \
    python3-pip \
    python3-notebook
python3 -m notebook
~~~

## docker

~~~bash
SERVER=localhost
PORT=8888
NAME=noteboot
docker run -d -p $PORT:8888 --name $NAME jupyter/base-notebook:x86_64-ubuntu-22.04
sleep 3
# これで表示されたURLにアクセス
docker logs $NAME 2>&1 | grep -o -e "http://127.0.0.1:8888/lab?token=.*" | head -n 1 | sed -e 's@/lab@/tree@g' -e "s@127.0.0.1:8888@$SERVER:$PORT@g"
~~~

## venvの追加

私は環境全体にnotebookをインストールして、venvにipykernelだけ入れて登録する形で使っている。

~~~bash
python -m venv projectname
source projectname/bin/activate
pip install ipykernel
ipython kernel install --user --name=displayname
~~~

## vs code

pythonがインストール済みならば

拡張機能を入れてnotebookを作成した（もしくはカーネルを選択しようとした）タイミングでipykernelなども自動でインストールされる様子。

https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter

---
# 参考

https://docs.python.org/ja/3/using/windows.html

https://docs.jupyter.org/en/latest/install/notebook-classic.html
findとfind_byの違い

# はじめに
`find`と`find_by`は、Railsでデータベースからレコードを取得するためのメソッドですが、いくつかの違いがあります。
findとfind_byの違いについて理解が曖昧だったため備忘録も兼ねてまとめます。
# 検索条件の指定方法
`find`: 主キー（通常はid）を指定してレコードを取得します。例えば、`User.find(1)`は`id`が1であるユーザーを取得します。

`find_by`: 様々な条件を指定して検索できます。例えば、`User.find_by(name: 'John')`は`name`がJohnであるユーザーを取得します。
```ruby
# 主キーを指定して取得
user = User.find(1)

# 条件を指定して取得
user_by_name = User.find_by(name: 'John')
```
# エラーハンドリング
`find`: 主キーが見つからなかった場合、`ActiveRecord::RecordNotFound`例外が発生します。主キーが存在しない場合、エラーが発生するため注意が必要です。

`find_by`: 該当するレコードが見つからなかった場合、`nil`を返します。そのためエラーが発生することはありません。
```ruby
# 主キーが見つからない場合の例外処理
begin
  user = User.find(100)
rescue ActiveRecord::RecordNotFound
  puts "User not found!"
end

# find_byではnilを返すため、エラーハンドリングが不要
user_by_name = User.find_by(name: 'Nonexistent')
puts user_by_name.nil? # true
```
# 取得されるオブジェクトの型
`find`: 単一の主キーに対応するレコードが見つかれば、単一のレコードを返します。

`find_by`: 条件に合致する最初のレコードを返します。該当するレコードがなければ`nil`を返します。
```ruby
# 単一の主キーに対応するレコードを取得
user = User.find(1)

# 最初の条件に合致するレコードを取得
user_by_name = User.find_by(name: 'John')
```
# まとめ
どちらを使用するかは、具体的な使用ケースやエラーハンドリングの方針によります。通常、主キーを使用して特定のレコードを取得する場合は`find`、特定の条件で検索する場合は`find_by`を使用します。
Storybookのtitleタグやfaviconを無理やり変更する


Storybookで[自作のライブラリのドキュメントサイト](https://phavuer.laineus.com)を作ったのですが、そうなると当然titleタグやfaviconを独自のものに変更したいわけですが、正規の設定ではできないっぽい？ので無理やり変更しました。

# 初期レンダリング時のtitleタグを変更

index.htmlに静的に設定される初期レンダリング時のtitleタグですが、どうせ直後にStorybookによって動的に変更されるため、あまり意味はありません。

ただ、シェア時などにシェア先のボットが読みに来る際は、js実行前の静的なhtmlを参照するため、こちらも一応変更しておきたいです。

Storybookの設定でどうこうしようと考えるのはやめて、ビルドされて生成されたhtmlファイルを書き換えちゃいましょう。

htmlファイルを読み込んで、titleタグ部分を文字列置き換えして上書きするスクリプトを作成します。

bashでもなんでもいいんですが、今回はnode.jsで作成しました。

```js:update-title.js
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const SITE_TITLE = '変更後のタイトル'

// ビルド後のhtmlまでのパス
const filePath = path.join(__dirname, 'storybook-static/index.html')

fs.readFile(filePath, 'utf8', (err, data) => {
  if (err) {
    console.error('Error reading the HTML file:', err)
    return
  }
  const updatedData = data.replace(/<title>.*<\/title>/, `<title>${SITE_TITLE}</title>`)

  fs.writeFile(filePath, updatedData, 'utf8', (writeErr) => {
    if (writeErr) {
      console.error('Error writing the updated HTML file:', writeErr)
      return
    }
    console.log('Title updated successfully.')
  })
})
```

これをビルドスクリプトの後に実行されるようにします。

```diff:package.json
  "scripts": {
    "dev": "storybook dev -p 6006",
-   "build": "storybook build"
+   "build": "storybook build && node update-title.js"
  },
```

# 動的に設定されるtitleタグを変更

Storybookは、ページ遷移時などにtitleタグを以下のような内容に更新します。

```js
[ページ名] ⋅ Storybook
```

ユーザーが実際に目にするtitleは、htmlファイルの静的なtitleタグではなくこちらになります。

また、Googleのクローラーもjsを実行した後のhtmlを読むため、SEO観点でもこちらが参照されます。

MutationObserverというクラスはDOMの書き換えを監視することができるので、Storybookによってtitleタグが変更された直後に書き換えを行います。

ページ名が設定されるのは活かして、「Storybook」という文言のみ置き換えました。

```js
new MutationObserver(records => {
  // 自分で書き換えたときも検知されてしまうので、無限ループにならないよう気を付けましょう
  if (document.title.includes('Storybook')) {
    document.title = document.title.replace('Storybook', 'サイト名')
  }
}).observe(document.querySelector('title'), { childList: true })
```

こちらのscriptを`.storybook/manager-head.html`あたりに書き込みます。

# faviconを設定

1. `public/favicon.ico`にアイコンを置きます。
2. `.storybook/manager-head.html`にfavicon.icoの読み込みタグを足します。
3. 『[初期レンダリング時のtitleタグを変更](#初期レンダリング時のtitleタグを変更)』と同様の手順で元々存在するfavicon読み込みタグを削除します。


# おわりに

Storybook、できあがるものは素晴らしんですが、色々カスタマイズしようとしたときの設定やらが難解すぎてキレそう。
世界一流のエンジニア思考法を読んで

# はじめに
昨今有名な著書である「世界一流のエンジニアの思考法」を読んだ感想や個人的に学びが特にあると感じた点を記載したいと思います。

あまり読める時間が取れないけど、どんな内容か気になる！と思う方は、「フェルミ」でも紹介されているので、動画を見るだけでも学びになるかと思います。

参考： 

https://youtu.be/pMrORF_-nvo?si=NDdQuRVRM0MrroJo


# 本の概要
この著書では、世界一流のエンジニアがなぜ圧倒的に仕事ができるのかが書かれています。
驚くことにパフォーマンスの高さは、頭の作りや才能という事ではなく、「思考法」から生まれているという事実があるそうです。

# 個人的に学びがあると感じた内容
詳しい内容は後述するとして、個人的に学びがあると感じた内容を記載します。（説明が無いトピックもあります）

1. 試行錯誤は悪
1. 「理解に時間を掛ける」を実践する
1. エキスパートに頼る
1. Be Lazyというマインドセット
1. コードリーディングのコツは極力コードを読まない
1. マルチタスクをやめる
1. 気軽に空気の大切さ
1. 意見が対立しても「否定」しない
1. 自己組織チーム
1. 仕事を楽しむ
1. 定時に上がる

### ①試行錯誤は悪
プログラムが上手く動作しない場合、ログを仕込んで試行錯誤した経験はないでしょうか？
私はあります。。ログをあちこちに入れて、どこが悪さをしているかを突き止めていることが多々ありました。

優秀なエンジニアが撮る手法としては真逆で、 **最初の一つのログだけを見て仮説を立て、手は一切動かさない**

「情報収集」→「仮説を立てる」→「仮説の検証」→「実行」というサイクルを回す。「仮説の検証」段階で不十分の場合は、「情報収集」に戻るという具合です。

### ②「理解に時間を掛ける」を実践する
著者がマイクロソフト社で働いた経験から、優秀なエンジニアでも理解には時間がかかるという事実があるということです。
理解が早いと感じるのは、基礎が出来ていてその知識を積み重ねているため、早いと感じるということです。
そもそも理解といるのは、
1. その構造を掴んで、人に説明できること。
1. いつでもどこでも即座に取り出して使えること
1. 知見を踏まえて応用が効くこと。

と著者は述べています。

初歩の初歩から簡単だと決めつけずに基礎を学習することで、応用することができる様になり、その結果として、試行錯誤も減るという具合に好循環が生まれます。

### ③エキスパートに頼る
**1つのことで二時間以上ブロックされたら、エキスパートの意見を頼り、他の仕事をした方が効率が良い** ということです。
個人的には40分ほど聞いてしまったも良いかと思っていますが、調べても考えても分からないことは、有識者に聞いた方が良いと思います。
この本を読んで改めて意識的に実践してみましたが、一人で悩むよりも早く解決することができ、無駄な時間の使わずに済みました。
他の人の時間を取ってしまうことになりますが、一人で一日中グダグダと考えているのであれば、有識者から10分ほどで知識を共有してもらう方がチーム全体で考えても効率が良いかと思います。

### ④Be Lazyというマインドセット
Be Lazy（怠惰であれ）
は「より少ない時間で、価値を最大化するという考え方」です。
達成するための習慣は以下の通りです。
・　望んでいる結果を達成するために、最低限の努力をする
・　不必要なものや付加価値の無い仕事を無くす
・　簡潔さを目指す
・　優先順位をつける
・　時間や費やした努力より、アウトプットと生産性に重点を置く。
・　長時間労働をしない様に推奨する
・　会議は会議の時間内で効率的かつ生産的に価値を提供する

 当たり前のことの様に感じますが、改めて意識してみると良さそうです。

 ### ⑤コードリーディングのコツは極力コードを読まない
 コードリーディングをする際は時間が掛かる時もありますが（特に新規リポジトリ）、隅々まで読むことはせずに、メソッド名などから処理を推測してコードの全体を理解することが大切ということでした。

 ### ⑥マルチタスクをやめる
 マルチタスクをしないというのは有名な話だと思いますが、どうしてもしてしまうこともありました。
 例えば、MTG中に内職してしまうなどです。
 会議で自分に関係のない話をしている場合でも、一切他の仕事はやらずに話に集中することが大切ということでした。

 ですが、どうしてもマルチタスクになってしまうこともあると思いますが、その様な時はどうするかというと、 **１日４時間は自分の仕事に集中する**ということです。
 その時間では、Slackなどでの連絡も全て無視して集中するということでした。
 そうすることでシングルタスクで集中することができ、とても効率が良くなります。
 連絡に関しては、確保していた４時間以外で返信することになります。個人的には1時間は集中し、30分は離れるを繰り返しても良いかなと思います。

 ### ⑦意見が対立しても「否定」しない
 相手を否定しない、相手のアイディアを否定しない、そして自分の考えとして意見をいうということを守れば、お互いのメンタルを傷つけることなく、議論の生産性を向上させることができるということです。

 相手も気持ちを考えた上で、反対意見を述べる場では「自分の意見では〜」と発言するのが良さそうです！

 ### ⑧定時に上がる
 私はキリが悪いからと、定時で上がらずに残業する派ですが、やはり生産性が低下するとありました。
 キリが悪かったとしても定時で上がる。強制的に定時に退勤することで、何の効率が悪かったかを振り返る。加えて、生産性を上げるために個人学習を行う。またしっくり睡眠や趣味の時間を増やす。 そういったことを実施することで、幸福度が上がると記載がありました。

今後なるべく実践してみようかと思いました！

 # 最後に
 この本はとても良書だと思いました！
 また、定期的に振り返りたいと思います。
 この本の面白いところは、優秀なエンジニアになるために、新たに何かを実施するのではなく、不要なことを減らして脳の負荷を減らし、生産性を高めるという事が明記されている事です。
 「脳の酷使をやめる」、「準備や持ち帰りをやめる」、「マルチタスクをやめる」、「情報の詰め込みすぎをやめる」、「管理をやめる」、「批判や否定をやめる」
 といった事です。
 そうした結果、驚くほど脳にスペースが生まれ、心身は楽になって、仕事は飛躍していくと記載されています。

 こちらに明記していない、アウトプットの重要性や失敗の歓迎など、とてもためになる事が多く記載されているので、一度読んでみることをお勧めします！

 ここまで、読んでいただきありがとうございました。
Goのfor-rangeのvalueはコピーであることが分かった

## 概要
Goのfor-rangeで渡される第２引数はコピーであることが分かったので投稿します。

Go: 1.21
## 実例
以下の例だと、`for i, v := range people`のvの値はpeopleの１つ目の要素のコピーなので、vの値を変えても、大元のpeopleの値は変更されません。
コピーなので`fmt.Println(&people[i] == &v)`のメモリアドレスの比較でもfalseになります。

```go
package main

import (
	"fmt"
)

type person struct {
	name string
}

func main() {
	people := []person{
		{name: "aだよ"},
	}

	for i, v := range people {
		fmt.Println(&people[i] == &v) // false
		v.name = "名前変わったよ"
		fmt.Println(v.F()) // 名前変わったよ
	}
	fmt.Println(people) // [{aだよ}]
}

func (p *person) F() string {
	return p.name
}
```

大元の値を変えたい場合は以下のようにコードを変更する必要があります。
```go
package main

import (
	"fmt"
)

type person struct {
	name string
}

func main() {
	people := []person{
		{name: "aだよ"},
	}

	for i := range people {
		people[i].name = "名前変わったよ"
	}
	fmt.Println(people) // [{名前変わったよ}]
}
```

ただ、大元の値（今回だと`people`）を変更して後続のコードに影響があるかもしれないので使用する場合は注意が必要です。
Optparseの使い方

optparseを使う機会があったので、整理を兼ねて使い方を書いてみます。

Rubyでは沢山のライブラリが用意されており、Gemfileを通して追加することなく使用できるものが沢山用意されています。
その中でも特に使用頻度が高いとされているものは組み込みライブラリと呼ばれ、requireを使って呼び出すことなくそのまま使用することができます。
optparseはコマンドライン上でオプションを受け取る為の呼び出しが必要な標準ライブラリです。
optparseを使う時は以下の３ステップを踏んで進めていきます。

1, `OptionParser`を使ってオブジェクトoptを生成
```ruby
require 'optparse'
opt = OptionParser.new
```

2, オプションを扱うブロックを作成
```ruby
opt.on('-m int') {|m| month << m.to_i}
```
`on`メソッドで`opt`オブジェクトに登録するオプションを定義する。
`-m`で数値として(intで数値として指定)受け取ったオプションをブロック内で`month`という変数に入れる。
オプションとして受け取った時は文字列になっているので、数値として扱いたい時は`to_i`メソッドで変更する。

3, コマンドラインで受け取ったオプションを分離する
```ruby
opt.parse!(ARGV)
```
ARGVにコマンドラインで受け取ったオプションと引数が代入されており、parseすることで引数だけに分離することができる

実際のコードを書いてみると以下のようになります。
```ruby
require 'optparse'
opt = OptionParser.new

month = []
opt.on('-m int') {|m| month << m.to_i}
p ARGV

opt.parse!(ARGV)

p month
```
上記のコードを実行した結果
```ruby
$ ruby sample.rb -m 12
["-m", "12"]
["12"]
```
`opt.parse!(ARGV)`の時点でオプションと引数が分離され引数が`month`に代入される
ルーティングの記述方法

# はじめに
ルーティングの記述方法の理解が曖昧だったため備忘録も兼ねてまとめます。
# ルーティングとは
Webアプリケーションにおいて、クライアントからのリクエストを処理するために、どのコントローラのどのアクション（メソッド）が呼び出されるかを指定する仕組みです。Railsでは、config/routes.rbファイルでルーティングを設定します。
```config/routes.rb
Rails.application.routes.draw do
    root "sample#index"
    get "/new" => "sample#new"
    post "/create" => "sample#create"
    resources :articles
end
```
# Rootとは
ルートは、アプリケーションのトップページを指します。上記の例では、SampleControllerのindexアクションがルートに設定されています。
# GETとは
indexアクションやshowアクションのようにデータの取得が目的のアクションです。
# POSTとは
createアクションのようにデータの送信や更新が目的のアクションです。
# resourcesとは
resources（リソースルーティング）は、CRUD操作（Create, Read, Update, Delete）に対応するURLとアクションを一括で設定できる方法です。上記のように`resources :articles`で生成されるルートは以下の通りです。
```terminal
GET      /articles           index       articles_path
GET      /articles/new       new         new_article_path
POST     /articles           create      articles_path
GET      /articles/:id       show        article_path(:id)
GET      /articles/:id/edit  edit        edit_article_path(:id)
PATCH    /articles/:id       update      article_path(:id)
PUT      /articles/:id       update      article_path(:id)
DELETE   /articles/:id       destroy     article_path(:id)
```

参考

https://qiita.com/matsukazu1112/items/548afb30227c760acb4b
曜日の判定 Python3編

https://paiza.jp/works/mondai/conditions_branch/conditions_branch__mod_step4


```py
X = int(input())

if X % 7 == 1:
    print('Sun')
elif X % 7 == 2:
    print('Mon')
elif X % 7 == 3:
    print('Tue')
elif X % 7 == 4:
    print('Wed')
elif X % 7 == 5:
    print('Thu')
elif X % 7 == 6:
    print('Fri')
elif X % 7 == 0:
    print('Sat')

```
たしか、もっと簡単にできたはず。。。
ヒントは配列

```py

x = int(input())
week = ["Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"]

print(week[x % 7])
```
きれいだなぁ。。。
はじめからやっておけば（汗）
効率的にテストコードを書こう

テストコードを効率的にできるのは便利ですね！

```ruby```
### 目的
- FactoryBotの概要と設定の方法を理解
- Fakerの概要と設定の方法を理解

### インスタンスを生成するコードを分離
#### FactoryBot
インスタンスをまとめることができるGem。他のファイルであらかじめ各クラスのインスタンスに定める値を設定しておき、各テストコードで使用する

### FactoryBotを導入
```ruby
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
end
```
`bundle install` 
specディレクトリ　に　factories/users.rb作成

### FactoryBotを使用してインスタンス生成を共通化
spec/factories/users.rb
```ruby
FactoryBot.define do
  factory :user do
    nickname              {'test'}
    email                 {'test@example'}
    password              {'000000'}
    password_confirmation {password}
  end
end
```

#### build
ActiveRecordの`new`メソッドと同様の意味を持つ
spec/models/user_spec.rb
```ruby
require 'rails_helper'
RSpec.describe User, type: :model do
  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      user = FactoryBot.build(:user)  # Userのインスタンス生成
      user.nickname = ''  # nicknameの値を空にする
      user.valid?
      expect(user.errors.full_messages).to include "Nickname can't be blank"
    end
    it 'emailが空では登録できない' do
      user = FactoryBot.build(:user)  # Userのインスタンス生成
      user.email = ''  # emailの値を空にする
      user.valid?
      expect(user.errors.full_messages).to include "Email can't be blank"
    end
  end
end
```
### 共通した記述を切り出す
#### before
それぞれのテストコードを実行する前に、セットアップを行うことができます
spec/models/user_spec.rb
```ruby
require 'rails_helper'
RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end

  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      @user.nickname = ''
      @user.valid?
      expect(@user.errors.full_messages).to include "Nickname can't be blank"
    end
    it 'emailが空では登録できない' do
      @user.email = ''
      @user.valid?
      expect(@user.errors.full_messages).to include "Email can't be blank"
    end
  end
end
```
beforeに定義する変数はインスタンス変数にする必要があります

### ランダムな値の出力
#### Faker
ランダムな値を生成するGem
#### Faker導入
Gemfile
```ruby
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
  gem 'faker'
end
```
`bundle install`

###Fakerを試す
```
rails c

[1] pry(main)> Faker::Name.initials(number: 2)
=> "XL"

[2] pry(main)> Faker::Internet.email
=> "georgina@yahoo.com"

[3] pry(main)> Faker::Internet.password(min_length: 6)
=> "9DfWbC3gZsZ5cL"
```

### Fakerを使用した記述を変更
spec/factories/users.rb
```ruby
FactoryBot.define do
  factory :user do
    nickname              {Faker::Name.initials(number: 2)}
    email                 {Faker::Internet.email}
    password              {Faker::Internet.password(min_length: 6)}
    password_confirmation {password}
  end
end
```
WebビューアでJavaScriptを実行をようやく使ってみた。

## WebビューアでJavaScriptを実行をようやく使ってみた。
今回は、19で新登場した[webビューアでjavascriptを実行](https://help.claris.com/ja/pro-help/content/perform-javascript-in-web-viewer.html)をようやく使っていきたいと思います。
まず初めにwebビューアでjavascriptを実行をGoogle先生で調べてみると、自作Formに値を入れて、Webビューアから値を戻す。
といった内容が広く一般的に書かれています。

あんまりこんなこと言いたくないんだけどね。
<strong>いやそれどこのタイミングで思ってどこで使うん。</strong>
※個人的な主観の為、気分を害された方には心よりお詫び申し上げます。

なので今回は、自分で使うタイミング作ってみました。

## ヤマト運輸で送り状作ります！
え？そんな急な…
~~私、送り状作る仕事してないから、そんなん言われてもピンとこんわ。~~
特段深い意味はないよ。
過去のサンプル探してたら、それしかなかったんだ。

皆様[ヤマト運輸](https://business.kuronekoyamato.co.jp/service/lineup/business_members/)って知ってますか？
ヤマトビジネスメンバーズの方はWebで送り状が作れるんです。

[送り状発行システムB2クラウド ログイン画面](https://bmypage.kuronekoyamato.co.jp/bmypage/servlet/jp.co.kuronekoyamato.wur.hmp.servlet.user.HMPLGI0010JspServlet)

今回は、こちらを例に作成していきます。
やっぱり具体的な例があった方がイメージしやすいと思うんですよね...私は。

19以前は、Webビューアの設定スクリプトステップでやっていましたよね？（圧）
ではまず思い出していきましょう。
```
Webビューア の設定[オブジェクト名:"Viewer";
URL:"javascript:
    function f()
      {
        document.getElementsByName('LOGIN_USER_ID')[0].value='ここにidでっす';
        document.getElementsByName('CSTMR_CD')[0].value='ここにcdでっす';
　　　　 document.getElementsByName('CSTMR_PSWD')[0].value='ここにpwでっす';
       };
    f();"]
```
という感じで、Webビューアの設定に直接JavaScriptを叩いていました。

じゃーこのまま、WebビューアでJavaScriptを実行スクリプトステップに移行していきたい。

```
Webビューア で JavaScript を実行[オブジェクト名:"Viewer";
関数名:"(()=>{
　　　　 document.getElementsByName('LOGIN_USER_ID')[0].value='ここにidでっす';
        document.getElementsByName('CSTMR_CD')[0].value='ここにcdでっす';
　　　　 document.getElementsByName('CSTMR_PSWD')[0].value='ここにpwでっす';
       })"]
```
これにてユーザー名等々入力できたのではないでしょうか。
いやー。楽しいですね。

## 最後に
いやー。ここまでやってきたんですけど、思ってるより結構手間取りました。
> まず初めにwebビューアでjavascriptを実行をGoogle先生で調べてみると、自作Formに値を入れて、Webビューアから値を戻す。
といった内容が広く一般的に書かれています。 
>
この上で話した通り、一般的に書かれている事がやっぱり大事なんですね。
これを理解した上で、関数名に直接書いて感動でした。
素晴らしい。
こういうの誰も書いてないっぽいので、誰か一助になれば、幸いです。

以上
ありがとうございました。
会社のリポジトリにプッシュしたとき「Couldn't connect to server」のエラーが出たらまずはVPNを確認しろ


# はじめに

若干ハマったので備忘録。

#### 【対象読者】
- 新卒エンジニア
- 初インターンの学生エンジニア
- 上記など、初めて会社のVPN使うような人


# 本題

会社貸与のPCでいつも通りプッシュしようとしていたときのこと。

以下のようなエラーが発生し、プッシュができなくなった。

```
fatal: unable to access 'https://github.会社ドメイン/リポジトリ名.git/': 
Failed to connect to github.会社ドメイン port 443 after 75145 ms: Couldn't connect to server
```

エラーを直訳すると以下の内容で **「リポジトリ、ひいては会社のドメインポートにアクセスできないからプッシュできんかったわ」** という感じ。

```
fatal: 'https://github.会社ドメイン/リポジトリ名.git/' にアクセスできません： 
github.会社ドメインポート443への接続に失敗しました： サーバーに接続できませんでした
```
<br>
今までは普通にプッシュできており、いきなり出てきたので「？」でした。

# 疑ったこと
- AndroidStudio内のGUIでプッシュしていたので、IDE内部のGitHub設定とかおかしくなったりしてるのでは？と疑ったが違った
- GitHubのsshkey周りが原因かと疑ったが違った

# 解決
結論は至極簡単、 **「会社のVPNが勝手に切れており、繋ぎ直したら治った」** です。

<br>
VPNとは以下のようなもので、会社のVPNに繋いでおくと家でのリモート業務でも社内のサーバー・システムに安全にアクセスできるというメリットがあるものになっています。

>VPNとは、Virtual Private Network（仮想プライベート ネットワーク）の頭文字を取った略語で、個人情報を盗み見されたり改ざんされたりするリスクから情報を守る技術のことです。VPNは「仮想専用線」と呼ばれることもあります。
>
>VPNを利用すると、仮想の暗号化されたトンネルをインターネット上に構築できます。つまり、インターネットを介して送信するデータを暗号化することで、第三者に情報が傍受されても読み取られることなく、個人情報を守ることができるのです。
>引用：https://jp.norton.com/blog/privacy/vpn
<br>
企業によりますが、業務の際このVPNを繋いでいないと社内のサーバーやシステムに何もアクセスできなくなる設定のものもあったりします。

今回がそれでした。

これも企業や設定によると思いますが、VPN接続は繋いでいてもふとした時（PCがスリープになった後とか）に切れていたりするので、社内のリポジトリにいきなりアクセスできなくなった場合はまずはVPN繋がっているか確認するのがよさそうです。
<br>

---

※oh、、弊社なかなかVPNで苦労した歴史が垣間見えますね、、

https://engineering.dena.com/blog/2020/06/vpn-for-telework/

https://engineering.dena.com/blog/2021/09/vpn-for-cj/
spfレコード

# SPFとは
、電子メールの送信元ドメインの詐称を検知する技術。ドメイン名についての情報を配布するDNS（Domain Name System）の仕組みを利用して、本当に送信元アドレスに記載されたドメインから送られてきたメールかを調べることができる。

# 実際の記載方法
DNSserverのゾーンファイルにて
```php:
seqvsbp.cn      text =

        "v=spf1 mx a ip4:x.x.x.x ip4:y.y.y.y ip4:z.z.z.z ip4:x.y.z.x ip4:a.b.c.d
```

注意なのが、メールヘッダーに記載されている全てのドメインをSPFが検知する訳では無い。
差出人と宛先人にそれぞれ二種類に分かれており、それがエンベロープFrom/ToとヘッダFrom/To。

https://baremail.jp/blog/2021/05/25/1377/


### コマンドでSPF確認
nslookupコマンドでの確認方法
```
nslookup -q=txt ドメイン名
```


# 実際の例
添付mailheaderより
* mail from : info@myna.go.jp
 → ヘッダFrom
* X-FROM-EMAIL: succ@seqvsbp.cn
 → エンベロープFrom

# SPFレコードチェッカー
ドメインのSPFレコードを検証するもので、以下のようなソフトウェアツールがある。

https://powerdmarc.com/ja/spf-record-lookup/
Flowとは？

![スクリーンショット 2024-01-05 13.44.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639815/2d88ac67-9416-f5ad-3e47-347a13684bba.png)

## コルーチンのFlowは<span style="color:#FA5882">非同期データストリーム</span>
#### 非同期とは？
 -> 二つの関数が一つ実行後終了し、次の関数を実行するのではなく、二つを同時に実行可能なことを非同期といいます。そして、仕事を終えて返すことが <span style="color:#FA5882"> __コールバック__ </span>
 
#### データストリームとは？
データを消費する消費者とデータを発行する発行者がおり、発行者は消費者に対して継続的にデータを発行することです。

コルーチンでデータストリームを使うためにFlowを使用します。

#### Flowのデータの核心は次の3つで構成されます。
- 生産者 (Producer)
- 中間演算子 (Intermediary)
- 消費者 (Consumer)

### 1. 生産者 (Producer)
生産者はデータを発行する役割を持ちます。

```kotlin
fun flowSomething(): Flow<Int> = flow { // flowブロック宣言
    repeat(10) { // 数字の繰り返し
        emit(Random.nextInt(0, 500)) // ランダム数字の発行
        delay(100L)
    }
}
```

### 2. 中間演算子 (Intermediary)
生産者がデータを生成したら、中間演算子はデータの修正を行います。

aというオブジェクトを発行した後、bというオブジェクトと交換できます。

中間演算子は生産者、消費者のような必須要素ではありません。

#### Flowがサポートする代表的な中間演算子
- map (データ変形)
- filter (データフィルタリング)
- onEach (データ演算実行)


```kotlin
fun main1() = runBlocking {
    flowSomething().map {
        "$it $it"
    }.collect { value ->
        println(value)
    }
}

fun main2() = runBlocking {
    (1..20).asFlow().filter {
        (it % 2) == 0
    }.collect {
        println(it)
    }
}
```

### 3. 消費者 (Consumer)
中間演算子が生産者が生成したデータを変換した後、消費者にデータを伝達します。
<span style="color:#FA5882"> Flowではcollectを使用してデータを伝達し、消費します。 </span> 
しかし、collectは複数のイベントで使用できません。複数のイベントを使用することができる<span style="color:#FA5882"> launchInが好まれます</span> 

消費者はUIを表し、ViewModelで必要な処理をviewで表示するものです。

```kotlin
fun events(): Flow<Int> = (1..3).asFlow().onEach { delay(100) }

fun main() = runBlocking {
    events()
        .onEach { events -> println("Event: $events") }
        .collect() // 複数のイベントに使用できない UI、ネットワーク呼び出し等
    println("Done")
}
```

```kotlin
fun readDateDatas(date: String) {
        viewModelScope.launch {
            repository.readDateData(date).collect {
                readDateData -> 
       }
   }
}
```
Oracle(SQL)勉強メモ

Oracleの知識が必要になったため、勉強した内容をメモとしてまとめます。
# RDSについて
・RDS(リレーショナルデータベース)とは、表形式でデータを管理する場所のこと。イメージとしてはExcelの表のようなもの。
#### 以下は基本的な言い回しのまとめ
表＝テーブル
表のデータを抽出、削除、更新、作成、定義する命令＝SQL
横列→行、レコード
縦列→列、カラム
行と列が重なった部分→フィールド
空白、無い状態→NULL(ヌル)　**※0、空文字ではない**
1行だけ特定できるレコード(IDなど)→主キー
他の表の主キーと関連付けるコード→外部キー、フォーリンキー
データの抽出の問い合わせ→クエリ

# SQL Plusについて
SQL Plusは、Oracleデータベースに接続し、データベース操作を行うためのソフトウェア。CUIで、データベースに対してSQLを利用しデータ操作を行う。
**※SQL Plusのツール専用コマンドがあり、SQLとは別物。**

# SELECT文の機能
以下2つはSELECT文の基本形。指定した表からデータを抽出する。
・`SELECT * FROM 表名;` (*＝全ての列)
・`SELECT 列名,列名,…,列名 FROM 表名;`
**※SQLは最後にセミコロンを付ける。SQL Plus用コマンドには最後に何も付けない。**

列に別名を付けて抽出する場合は以下の文を利用する。
・`列名 AS 列別名`(SELECT文の抽出列｛*や列名,列名,…,列名｝に差し込む)　
# よく使うSQL Plus用コマンド
・`SET PAGESIZE 数字`(デフォルトは14) 1ページの行数を設定する。
・`SET LINESIZE 数字`(デフォルトは80) 1行の長さを設定する。
・`/` 直前のSQLを再実行する。
・`ED` 直前のSQLをメモ等で編集できる機能。SQL Plus用のコマンドは編集できない。
Amazon QuickSight Training and Certificationの学習まとめ

# はじめに
タイトルの件についてここでまとめていきます。
参考サイト
- 
https://explore.skillbuilder.aws/learn/course/6406/play/20257/introduction-to-amazon-quicksight-japanese-ri-ben-yu-chuiki-tie-ban

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [QuickSightの概要](#Chapter1)
1. [使用できるデータ](#Chapter2)
1. [使用例](#Chapter3)
1. [QuickSightを使う理由](#Chapter4)
1. [ML Insightsの紹介](#Chapter5)
1. [QuickSightの仕組み](#Chapter6)
1. [SPICEとは](#Chapter7)
1. [料金モデル](#Chapter8)
1. [機能一覧について](#Chapter9)
1. [QuickSightの無料トライアル](#Chapter10)

<a id="#Chapter1"></a>
# QuickSightの概要
高速対応のBIツール
セッション単位の課金なので、お金を節約できる
以下を提供している
・安全性とコンプライアンス
・グローバルな可溶性
・組み込み済みの助長性

<a id="#Chapter2"></a>
# 使用できるデータ
以下画像の通り、さまざまなデータを使用可能
![スクリーンショット 2024-01-05 12.18.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/23472b8c-4deb-7f07-b5e4-d41ce86be333.png)


<a id="#Chapter3"></a>
# 使用例
- 社内BIプロジェクト用
-企業はレポートとダッシュボードを作り組織内で共有する

- デベロッパー/ISV
-顧客向けの豊富な分析機能をポータルなどに加えている

- パワーユーザー
-セルフサービスでアクセスできるデータ分析などを行える
![スクリーンショット 2024-01-05 12.20.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/96e02199-5e24-f49a-eeb6-869caff9f7e0.png)


<a id="#Chapter4"></a>
# QuickSightを使う理由
- 誰でも簡単にレポートを作れる。
- PC以外に携帯からでもアクセスできる。
- ユーザーが拡張しやすい
- 業界初のセッションごとの課金制度
- 他のAWS製品と相性がいい
- 自社のホームページや独自のアプリにシームレスにダッシュボードを埋め込むことができる
- 日時、週次、月次のレポートをEメールで送ることができる。
- ユーザー単位、グループ単位でレポートを送れる
- Eメールでレポートを送るときはセッション単位の料金を採用している。

<a id="#Chapter5"></a>
# ML Insightsの紹介
・機械学習による異常検出
・機械学習による予測
・自然言語による自動説明文


<a id="#Chapter6"></a>
# QuickSightの仕組み
- どのブラウザからでもアクセスできる。
- ソフトウェアのアップデート、インストールが不要。
- どこからでもデータへアクセス可能
![スクリーンショット 2024-01-05 12.36.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/34cb8858-025c-8353-0260-a02c19b47272.png)


<a id="#Chapter7"></a>
# SPICEとは
- 超高速インメモリエンジン
- アカウントやダッシュボードのユーザー数に限らずパフォーマンスを提供できる
- QuickSight内でダッシュボードを作成したときに以下のいずれかを選べる
-ダッシュボードに直接データソースからデータを照会させる
-SPICEにデータをインポートする。
![スクリーンショット 2024-01-05 12.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/84d8d5b2-c858-8954-e22a-2c13737b97a5.png)


- SPICEにデータをインポートしている場合はすべての紹介とユーザーアクティビティを保護し、コストを節約します。(元のデータソースに負担をかけない)
※しかしながら、インポートできるデータ量は限られ、お金もかかってくるので、頻繁に参照するテーブルだけSPICEに取り込むといった工夫が必要

<a id="#Chapter8"></a>
# 料金モデル
セッションとはログインしてから30分のセッションで0.30USDかかる
しかしながら、Readerは5USDまでが上限なので、5USDに達したらそれ以上は課金されない。
![スクリーンショット 2024-01-05 12.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/63d95a45-c36c-0c02-7a7d-8dbba5c60d67.png)


Readerの料金利用シナリオ
![スクリーンショット 2024-01-05 12.58.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/1d0072e6-7b48-0e8a-09b3-7ca5ca2e7d1d.png)



スタンダードエディションもある
![スクリーンショット 2024-01-05 12.59.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/dca0a00e-a1f6-9edc-52c6-3770967ec464.png)


<a id="#Chapter9"></a>
# 機能一覧について
- https://aws.amazon.com/jp/quicksight/features/
- https://aws.amazon.com/jp/blogs/news/coming-november-2023-a-new-analysis-experience-on-amazon-quicksight/

<a id="#Chapter10"></a>
# QuickSightの無料トライアル
- https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/signing-up.html
UIからテーブルを設計する具体的な手順メモ

# 概要
テーブル設計のやり方について備忘録と頭の中の整理のために残しておきます。

やることはまず完成とは何がどういう状態なのかを定義すること、
テーブル設計ではテーブルが完成しているとはどういう状態かを定義します。
その後完成のために必要なタスクを抽出し行なっていきます。

DBはMySQLを想定しています。

# テーブル設計の完成の定義

- 開発するソフトウェアに必要なデータがMECEで永続化できる構造を定義すること

# 必要なタスク

- UIを元に必要なデータを抽出する
- 抽出したデータを元にRDBMSの構造に当てはめる

# 具体的な流れ
タスクを具体的に実行していく方法を説明します。

### 1.必要なカラムを定義していく

例：Qiitaのようなサービスを作る場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763385/5a8a56cd-fb78-83f4-3349-7b319f9cf23f.png)


枠で囲った部分は記事の一覧がリストで表示されます。

記事の一覧は記事を複数集めたものなのでまずは一つの記事がどのような要素で構成されているのかを確認しましょう。

トップページの一覧に表示されている記事を構成するのは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763385/794e34aa-b727-9ef1-d00e-8e8874f81a19.png)

- プロフィール画像
- ユーザー名
- 記事タイトル
- 投稿日
- タグ
- LGTM
- ストック

があるとわかります。

他にも必要なカラムを定義します。

記事の一覧を定義したので、次は記事の詳細ページを定義します。

記事の詳細で使われるデータは記事の一覧と共通する部分が多くあります。

記事の詳細にのみ必要なデータをピックアップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763385/6b8736dc-faa5-1657-f866-f8cf931f9eaf.png)



新たに必要とわかったのは

- 更新日
- 閲覧数
- 記事本文

です。

更新日と記事本文は記事にまつわるデータなのでPostsテーブルに定義し、閲覧数は分析などにも使われるためViewsテーブルに定義しましょう。

画面右サイドメニューの目次についてはテーブルにしなくても本文の見出し1をフロントで処理することで実現できるのでテーブルにしません。

また左サイドメニューのSNSボタンを使うことで自分たちのサービスのデータが変更されたり作成されたりすることはないのでテーブルは作成しません。

これらを大まかにテーブルに分けると下記のテーブルたちが少なくとも必要とわかる。

タグやストック、ユーザーとポストの紐付けには一般的に中間テーブルが必要なのでそこも追加する。

テーブル名キャメルケースで複数形、中間テーブルはアルファベット順でテーブル名同士を繋げる

カラム名は次の項で触れますがスネークケースでつけます

- Usersテーブル
    - プロフィール画像
    - ユーザー名
- Postsテーブル
    - 記事タイトル
    - 投稿日
- Tagsテーブル
    - タグ名
- Stocksテーブル
    - ストック名
    - ストック追加日
- Lgtmsテーブル
    - user_id
    - post_id
- PostsUsersテーブル（中間テーブル）
    - post_id
    - user_id
- PostsTagsテーブル（中間テーブル）
    - post_id
    - tag_id
- PostsStocksテーブル（中間テーブル）
    - stock_id
    - post_id

他にもまだまだ必要なカラムは出てくると思いますが、UIから必要なカラムを定義する作業を紹介できたので次にデータ型を決めていきます。

## カラムの詳細を決める

おおよそ必要なカラムがわかったのでテーブルの設計図を作ります。

まずは表に書き出すと整理できて良いと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763385/7911619f-ea3a-30fd-f234-4f81d022b389.png)



データ型の決め方は

ID関連 → integer

テキスト関連（タイトルやディスクリプションなど） → string

記事本文 → text

フラグ系 → integer（boolよりこちらの方が拡張性があるため）

作成日、更新日 → timestamp

で決めています。

qiitaのひと記事あたりの平均文字数は5700文字のようです。（最大で55万文字の記事もあるようです。）[参考記事：結局Qiita記事ってどれぐらい書けばいいのさ
](https://qiita.com/canonno/items/57f917147b3d6ae106e9)

記事本文は3万文字あれば十分と思われるのでtext型にしています。

フラグ系があった際はboolよりintegerの方が良いです。 

例えば有料プランがあるサービスを作る際に

ユーザーが有料プランか否かを判定して表示するデータを切り替える処理がある場合、条件分岐的にはついついboolで実装したくなります。

しかしユーザーのプランが2つ以上に増える可能性がある場合、boolで実装しているとデータ型を変えることになります。

そのためデータの種類が増える可能性がある際はintegerの方が無難です。

中間テーブルやLGTMテーブルには外部キーをつけています。

ユニーク制約をつけるカラムは以下になります。

- Stocks
    - user_idとname
- PostsTags
    - post_idとtag_id
- PostsUsers
    - post_idとuser_id
- StocksPosts
    - stock_idとpost_id

Stocksのuser_idとnameについては同じユーザーが同じ名前のストックを作成できないようにつけます。

他のテーブルは中間テーブルです。同じ組み合わせが登録されてないようにつけておきます。

一旦ここまでできたらチームのメンバーとレビューしてブラッシュアップしていくことでいいテーブルができると思います！

UIがあれば必要なデータがわかりやすいのでこのやり方だとカラムを過不足なく定義できるのでおすすめです。
深さ優先探索で画像中の島を構成するピクセルを列挙する

# 動機
Pietという少々変わったプログラミング言語の存在を知った。普通のプログラミング言語において、ソースコードはテキストファイルで作成される。Pietでは、画像がソースコードの役割を果たす。面白いので、インタプリタを作ってみたいのだが、画像中の同色の領域を検知する必要がある。

そこで、準備として、始点のピクセルを与えたとき、そのピクセルに接続されているピクセルを列挙するプログラムを作ってみることにした。ここでは、与えられたピクセル（画素値は非ゼロ）の上下で画素値非ゼロのピクセルを接続されたピクセルと定義することにする。

# 深さ優先探索(DFS)
DFSで実装することにする。DFSはこんな感じで実装できる。
```
root nodeをスタックにpushする;
while(stack.size()!=0)
{
    stack.pop();//これが現在node
    現在nodeの全ての子nodeをpushする;
}
```

# 実装
```c++
#include "CImg.h"
#include <stack>
#include <vector>
#include <iostream>
using namespace cimg_library;
using namespace std;
using Pos = std::pair<int, int>;

bool is_island(const CImg<unsigned char> &img, Pos pos)
{
	int i = pos.first, j = pos.second;
	if (img(i, j, 0, 0) != 0 || img(i, j, 0, 1) != 0 || img(i, j, 0, 2) != 0) return true;
	else return false;
}

int main(int argc, char **argv)
{
	CImg<unsigned char> img(argv[1]);
	int width = img.width();
	int height = img.height();

	stack<Pos> spos;
	Pos pos0(0, 0); // 探索始点
	spos.push(pos0);

	std::vector<Pos> island;
	
	while (!spos.empty())
	{
		Pos pos_cur = spos.top(); spos.pop(); // 現在の探索ノード
		island.push_back(pos_cur);
		
		// 子ノードを全てpushする
		for (int di = -1; di <= 1; di += 2) // 左右を探索
		{
			Pos pos = pos_cur;
			pos.first += di;
			
			if (pos.first < width && pos.first >= 0 && is_island(img, pos))
			{
				if(find(island.begin(), island.end(), pos) == island.end()) spos.push(pos); // 既にpushした要素をpushしないようにする
			}
		}

		for (int dj = -1; dj <= 1; dj += 2) // 上下を探索
		{
			Pos pos = pos_cur;
			pos.second += dj;

			if (pos.second < height && pos.second >= 0 && is_island(img, pos))
			{
				if (find(island.begin(), island.end(), pos) == island.end()) spos.push(pos); // 既にpushした要素をpushしないようにする
			}
		}
	}

	CImg<unsigned char> img_out(width, height, 1, 3, 0);
	for (auto e : island)
	{
		cout << e.first << " " << e.second << std::endl;
		img_out(e.first, e.second, 0, 0) = 255;
		img_out(e.first, e.second, 0, 1) = 255;
		img_out(e.first, e.second, 0, 2) = 255;
	}
	img_out.save("out.bmp");

	return 0;
}
```
入力画像：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/8de36a8d-1e10-680c-36ef-f0c680375d18.png)
出力画像：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/9c65a212-4382-615e-bcd7-ecdc1c6c48b8.png)

出来てそう。
バグが見つかったら直す。
VSCODEの拡張機能を使用して日本語表示に切り替える

## VSCODEを日本語表示に切り替える

VSCODEを自分のPCにインストールしたので、
日本語表示に切り替える方法を記載します。


また本記事は、あくまでも**自分が振り返る際のメモ程度の記事**になるため、
専門性はございません。あらかじめご了承ください。


下図は、インストールを終えアプリケーションを開いた画面
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663716/37441755-824e-7840-d601-171f9912b2dc.png)


![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663716/39c09de7-2d32-75c1-f8aa-3526e022b756.png)

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663716/a0b71c88-b46f-f002-4c72-5d0817594d8a.png)

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663716/e8749dd2-4d80-3164-009e-b2c04df4343c.png)

以上です。
これでHTMLとCSSの学習を進めようと思います。
勉強会やアウトプットを始めたい時のTips

# これは？

今年から社内勉強会を始めることになったが、ノウハウが何もなく、手探りで四苦八苦しながら、勉強会の形を作っていくノート

適宜アップデートしていく

# 目次

- 勉強会って何をするの？
- 楽にスライドを作る
- qiitaで投稿・オーガナイゼーションに紐付ける

# 勉強会って何をするの？

ぶっちゃけ、まだよくわからない

何をするにしても、主催する本人ががある程度知見があり、楽しめる内容で無いと結構つらい気がする

そのため、自分がやりたい・知りたい・やってて楽しいことでいくつか書き出し、アンケート取るのが手っ取り早い気がする

## ざっくりした種類・形式

- ディスカッション（テーマなり本なり、みんなで討論）
- 発表（一人が共有）
- ワークショップ（スライド見ながら実際に手を動かす）
- ミッション・ハンズオン（宿題）形式

やること以上に、環境の用意（本や機材・実行環境の準備）をどう行うかが問題

対象となる人を踏まえ、限られた時間で環境の用意や理解ができる、**難しくはないが、知らなそうなこと**が良さげ？

インタープリタ, jupyter, playground的なものが使えるとやりやすい？

---

# 楽にスライドを作る

今年から社内勉強会を始める事になりスライドを作る必要があった。
しかしどうにもpowerpointというものに馴染めないでいる。

そのため、markdownからスライドを手軽に作れるMarpの紹介。

## 要約

- 凝ったことをしなければとても簡単
- 図はsvgが使える（draw.ioとかでつくる）
- 自分 or 会社用のスタイルシートを作った方がよい

## TL；DR

1. vs codeで拡張機能検索”marp”
2. 下のように書いていく
2. [これに化ける](#スライド等の埋め込み)

~~~
---
# marpをオンに
marp: true
# ページ番号
paginate: true
# テーマ
theme: default
title: 
#class: invert # 白黒反転
#header: "**〇〇株式会社など**"
#footer: "by 作成者名など"
---

# 【社内勉強会pre】 MCPCモバイル２級

傾向と対策

<!--
backgroundColor: white
paginate: true
-->

---

スライドつらつら

---
~~~
## 参考

公式

https://marpit.marp.app/directives

https://github.com/marp-team/marp

概要

https://qiita.com/tomo_makes/items/aafae4021986553ae1d8

https://forest.watch.impress.co.jp/docs/review/1422278.html


見た目の変更等

https://qiita.com/YoshikiIto/items/74b3d786266b1de3ed93

https://zenn.dev/cota_hu/books/marp-beginner-advanced/viewer/create-2

https://qiita.com/aikige/items/be0bcfea8768e1cf02b8

小技

https://www.kageori.com/2022/02/marp.html

---

# qiitaで投稿・オーガナイゼーションに紐付ける


https://help.qiita.com/ja/articles/qiita-post

https://help.qiita.com/ja/articles/qiita-org-article

特に難しいことはなく、`投稿する` → `記事を新規作成`をクリック

2画面でプレビューしながらmarkdownを編集する

公開設定からオーガナイゼーションを選択


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472791/8433c010-31cb-8121-0e1b-ceb5cf251686.png)

小ネタを下書きに溜め込んで後で加筆修正するのがおすすめ？？

## スライド等の埋め込み

https://qiita.com/Qiita/items/612e2e149b9f9451c144


様々なコンテンツを埋め込み可能

googleスライドの場合、インポート・作成の後`ファイル→共有→webに公開`でしたの様なHTMLを取得できる。

コードブロックで括らずに、そのままペーストすると下のように埋め込みができる。

~~~
<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRiUi1wByYZl1iPXYHSvprJTJpq8b9FNglalUgFwPxJgMMcR6iRFo2qTVYjXMJDsqSYi7fIc51ceAch/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
~~~

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRiUi1wByYZl1iPXYHSvprJTJpq8b9FNglalUgFwPxJgMMcR6iRFo2qTVYjXMJDsqSYi7fIc51ceAch/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>