OmniAICreator/Qiita-1.07M huggingface dataset:
GitLabにおけるソースコード管理は作業前に Draft Merge Request がオススメ

## Draft Merge Request とは
- 下書き状態のマージリクエスト
- リクエストを送ってコードレビューしてもらうことはできるが、下書き状態のためマージすることができない
- 作業途中だけど一旦レビューしてもらいたい時によく使われる

[参考：Draft Merge Request（公式)](https://docs.gitlab.co.jp/ee/user/project/merge_requests/drafts.html)

## よくある通常の流れ
![Mask group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1092366/4957ac3c-0062-bd00-8fba-589bce727faa.png)

## 作業前に Draft MR の流れ

![Mask group (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1092366/657a208c-143b-5d81-1d65-630926e0ed30.png)


### メリット
- 誰がなんの作業をしているかがMR一覧を見れば一目で分かる
- Draftなので誤ってマージしてしまう恐れがない


## なおGitHubにおいては
GitHubにも同様の機能に「[Draft Pull Request](https://github.blog/jp/2019-02-19-introducing-draft-pull-requests/)」がありますが、GitLabと異なり、何も変更していない状況だとDraft Pull Request できないようでした。

とはいえ、誤って承認してしまうリスクを抑えたり、作業途中だけどフィードバックを受けたい場合にと便利なことには変わりないかと思います。
paiza.ioでelixir その199

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
n行目の行を返す関数と先頭に'1'がある行の行番号を返す関数を書け。

# サンプルコード

```
defmodule Va do
	use Agent
	def start_link() do
		Agent.start_link(fn ->
			0
		end, name: __MODULE__)
	end
	def get() do
		Agent.get(__MODULE__, fn v ->
			v
		end)
	end
	def set(x) do
		Agent.update(__MODULE__, fn v ->
			x
		end)
	end
end
defmodule Src do
	use Agent
	def start_link() do
		Agent.start_link(fn -> 
            ""
		end, name: __MODULE__)
	end
	def set(x) do
		Agent.update(__MODULE__, fn v ->
	        x
		end)
	end
	def get() do
		Agent.get(__MODULE__, fn v ->
			v
		end)
	end
	def getn(n) do
		Agent.get(__MODULE__, fn v ->
	    	Enum.at(String.split(v, "\n", trim: true), n - 1)
	    end)
    end
    def getl("end") do
        0
    end
	def getl(a) do
		Agent.get(__MODULE__, fn v ->
            Enum.reduce(String.split(v, "\n", trim: true), 1, fn l, n ->
	    	    if String.starts_with?(l, a) do
	    	        Va.set(n)
	    	    end
	    	    n = n + 1
	        end)
	        Va.get
	    end)
    end
end

Va.start_link
Src.start_link

str = """
1 kl
2 ll
3 kjh
4 edf
"""
Src.set(str)
Src.getn(4)
|> IO.puts
Src.getl("1")
|> IO.puts






```

# 実行結果

```
4 edf
1
```

# 成果物

https://paiza.io/projects/MMV8JdFZJbzd-b9GvPrOkA?language=elixir


以上。
データベースのレプリケーション

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はデータベースのレプリケーションについて更に詳しく調べてみましょう！

![インスタスライド_202302102.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/6a20c98f-e3fc-842b-c402-ce372cd3aa3f.gif)


# レプリケーションとは
データベース管理システムが持つ分散機能。

■双方向レプリケーション
■片方向レプリケーション
　（トランザクション型）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/e207032d-dbb0-4699-d57c-5cbe7fb65e90.png)

# 双方向レプリケーション
マスターデータベースからとレプリカへ、互いにデータを交換しあい、常に内容が一致するようにできているため、一ヶ所でデータを更新すると、マスターとすべてのレプリカに自動的に更新内容が伝播する。

双方向のため各々のデータの整合性を確認しながらの更新となるため、パフォーマンスは悪い。あまりお勧めでない。

テーブル毎に運用を決め、片方向レプリケーションがベター。

# 片方向レプリケーション
マスターデータベースからとレプリカへのみデータの更新内容の反映を行う。

更新データは、トランザクションログとして配布される。

両者のデータ整合性確認が不要のため、パフォーマンスは高い。

# 色々なレプリケーション
集中型レプリケーション

東京本社から各支店で片方向でデータを送信
発生データを一元管理できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/777d8dba-4309-cf07-b0d7-70e5d45a4060.png)

中継型レプリケーション

大阪からのデータは、東京本社で一度中継する
事により通信コストを下げる事が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/7c58ab02-5523-cf16-b6ba-a0f1725aa2bd.png)

収集型レプリケーション

自立部門方の組織の場合に各々のデータを収集する形。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/a4e97928-5f16-88f7-e3b0-271eacbb316d.png)

# まとめ
ーレプリケーションはDBの分散機能

ー双方向・片方向のレプリケーションがある

ー色々なレプリケーションがある

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
LVGLでイメージボタン

イメージボタンが押されているときの見た目の判別をつけるためにアウトラインを設定
```
LV_IMG_DECLARE(testiii);
lv_obj_t * img1 = lv_imgbtn_create(lv_scr_act());
lv_imgbtn_set_src(img1, LV_IMGBTN_STATE_RELEASED,  &testiii, 0, 0); //画像の設定(押されていないとき)
lv_imgbtn_set_src(img1, LV_IMGBTN_STATE_PRESSED,  &testiii, 0, 0);  //画像の設定(押されているとき)
lv_obj_set_pos(img1, 100, 100);
lv_obj_set_size(img1,64,64);  //サイズWidth,Height
static lv_style_t style;
lv_style_init(&style);
lv_style_set_outline_width(&style,2); //アウトラインの太さ
lv_style_set_outline_color(&style,lv_color_black());  //アウトラインの色
lv_obj_add_style(img1, &style,LV_STATE_PRESSED);  //イメージボタンの押されているときのスタイルにアウトラインのスタイルを設定
```
![style.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494758/7973f813-7a3d-d895-7616-5418e8814a67.png)

画像をlvgl用に変換するツール
https://lvgl.io/tools/imageconverter
そのままだと初期値代入部分で構文エラーが出るので少し書き直す
```
const lv_img_dsc_t testiii = {
  .header = {
    .cf = LV_IMG_CF_TRUE_COLOR,
    .always_zero = 0,
    .reserved = 0,
    .w = 64,
    .h = 64,
  },
  .data_size = 4096 * LV_COLOR_SIZE / 8,
  .data = testiii_map,
};
```
MacでRaspberry Pi Zero 2 WにSSH, Wi-Fi経由で接続するセットアップ方法

Raspberry Piのデフォルトのユーザ名とパスワードが`pi`, `raspberry`ではなく、カスタム設定が必須に変わっていたのでセットアップ方法を簡単にまとめました。

1. Raspberry Pi OSをダウンロード
https://www.raspberrypi.com/software/operating-systems/
    > **Raspberry Pi OS Lite**
    Release date: February 21st 2023
    System: 64-bit
    Kernel version: 5.15
    Debian version: 11 (bullseye)

    .xzでダウンロードされるがそのままでOK

2. OSイメージをSDカードに焼く
https://www.balena.io/etcher

3. Finderから消えていたらSDカード抜き差しで再認識

3. `touch /Volumes/boot/ssh` (空ファイル生成)

4. Wi-Fi情報をSDカード内のファイルに書き込む
    ```/Volumes/boot/wpa_supplicant.conf
    country=JP
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    
    network={
        ssid="NETWORK-NAME"
        psk="NETWORK-PASSWORD"
    }
    ```

6. パスワードのハッシュを生成

    ```sh
    echo 'mypassword' | openssl passwd -stdin
    ```

7. ハッシュ化されたパスワードを`userconf.txt`に保存

    ```/Volumes/boot/userconf.txt
    username:encrypted-password
    ```

8. SDカードをRaspberry Piに戻し電源を接続
    数十秒すれば `ssh pi@raspberrypi.local` で接続可能に

#### 参考文献
https://desertbot.io/blog/headless-raspberry-pi-zero-w-2-ssh-wifi-setup-mac-windows-10-steps
https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022/
【AtCoder入緑記事】地方国立大数学科のAtCoder挑戦記 -入緑編-

# 1.挨拶
どうもこんにちは、TsubakiMintです。AtCoderで入緑したので、色変記事を書きます。また少し前に入茶記事も書いておりますので、併せて読んでいただけると幸いです。

# 2.自己紹介
入茶記事と同じです。
- ハンドルネーム:TsubakiMint
- 所属:地方国立大の理学部数学科学部生
- 使用言語:Python3
- 競プロを始めた時期:2022年12月

# 3.入緑まで
![9280104A-6F9E-4DB6-B494-C679B8378945.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/2ed0d1ce-1b78-1107-0099-4ea1e8d16a3f.jpeg)
## 3.1.①一度目の上昇期
入茶後も最初は順調にレートが伸びました。このとき、「これはすぐにでも緑になれるだろう」とおもっていました。
## 3.2.②まさかの停滞期
![0556DCA0-85D4-4973-A3AE-757965F77A6B.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/641c0313-30d1-259e-1e78-d0460ff1e491.jpeg)
高をくくっていた所に訪れた停滞期です。
### 3.2.1.ARC155
![5661405A-B2A2-430C-AA76-70DADD7C22F3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/646abfde-05f7-8b27-c9de-ee2490cac76f.jpeg)
この回はA、Bが共に水diffの回でした。残念ながら0完となり、レートが32下がりました。とはいえ、運が悪かったと切り替えることにしました。
### 3.2.2.ABC288
![94C7A372-33FA-4E93-8BB3-883334EABF97.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/04eac451-860b-4c15-7c32-cdf9dc179579.jpeg)
この回は、Cが茶diff、Dが青diffの崖回でした。（「予選仕様のため中盤が難しくなる」というアナウンスがありました。）
Cの早解きで水diffが出た人もいたそうです。
Cの早解きができていれば高いパフォが出ていたので、レートが下がったのは精進不足がゆえと考え、更に精進を続けるべきと心に決めました。
## 3.3.③再びの上昇期、緑へ
精進の結果再びレートが伸び始め、入緑することができました。

# 4.今後の展望
最近のコンテストでは、本番中に緑diffが解ける割合が半々です。水色になるためには緑diff安定が必要と考えております。
最近の精進ではdiff400以上の問題を下から埋めています。
![4DA44DC1-C183-4A2A-BAFC-5BD82F316C4A.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/ac6f4b99-a19f-fe7d-8cf0-b0c8207c3636.jpeg)
こちら、AtCoder Problemsの精進グラフです。

# 5.さいごに
読んでいただき、ありがとうございます。入水したらまた記事を書くと思いますので、その時はまたよろしくお願いします。
【Django】form_validが実行されないときの対処法

# 生じた問題
views.pyの中でCreateViewのform_validをオーバーライドしたものの，実行されなかった．
```views.py

class CreateReviewView(CreateView):
    # 他の動作は省略
    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

```

# 解決策
from_invalidでform.errorsを出力する．

```views.py

class CreateReviewView(CreateView):
    # 他の動作は省略
    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)
    
    # 以下のコードを追加
    def form_invalid(self, form):
        print(form.errors)
        form.instance.user = self.request.user
        return super().form_invalid(form)

```
サーバーを立て直し，上手く行かなかった動作をもう一度行います．
当然今回も上手く行きませんが，エラーの内容を確認することができます．
私の場合は以下のような出力が返ってきました．
```
<ul class="errorlist"><li>text<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
```

つまりtextというフィールドが存在していないとのこと．htmlファイルを確認したところ，inputタグ内のnameが，本来はname=textとなっている必要があったところがname=testとなっており，誤字によって実行されていなかったことが分かりました．

# まとめ
+ form_validが実行されないときはform_invalidが実行されていることがある．
+ form.errorsを出力することで，エラーの内容を確認できる．

こういう誤字ってVSCodeのError Lensとかですぐ確認できそうだけど，私のWSL環境ではError Lensが上手く働いてくれませんでした．残念！
JavaScirptの基礎まとめ 基礎編3～これは絶対に覚えておくべき～

# JavaScript 基礎編3
JavaScript基礎編最後です。
前回の記事は[こちら](https://qiita.com/shinry/items/0a5ba30676e3b72cdc01)

## DOM(Document Object Model)
windowオブジェクト配下のDocumentオブジェクト。
HTMLを操作できる。
- 特定の要素を探す
```javascript
document.querySelector(CSSセレクタ);

//例
const element1= document.querySelector('.sample'); //.は指定するクラスを呼び出すときに使う
const element2= document.querySelector('#sample'); //#は指定するidを呼び出すときに使う

element1.textContent = 'テキスト1';
element2.textContent = 'テキスト2';
```
- 特定の要素をすべて探す
```javascript
document.querySelectorAll(CSSセレクタ);
```
- querySelector()/querySelectorAll()以外
特定要素を探す方法として、querySelector()/querySelectorAll()以外の方法もある。
```javascript
getElementById(ID名);
getElementsByClassName(クラス名);
getElementByTagName(タグ名);
```
getElement系は取得する要素に応じてメソッドを使い分ける必要があるので、特別な意図がない限りquerySelector()/querySelectorAll()を使うのが良い。
getElement系はページの表示速度を向上させたいときなどに使う。
- 要素のテキストを変更する
```javascript
要素.textContent = '変更したいテキスト';

//例
const p = document.querySelector('p');
p.textContent = '変更します';
```
- 要素の属性を変更する
```javascript
//指定属性の値を参照する
要素.属性名

//指定属性の値を変更する
要素.属性名 = '変更したい値';
```
- cssスタイルを変更する
```javascript
要素.style.cssプロパティ名 = '値';

//例
const p = document.querySelector('p');
p.style.fontSize = '36px';
```
- クラスを削除する
```javascript
要素.classList.remove('削除するクラス名');
```
- クラスを追加する
```javascript
要素.classList.add('追加するクラス名');
```
- 指定のクラスを置換する
```javascript
要素.classList.replace('対象クラス名','置換クラス名');
```
- 要素を作成する
```javascript
document.createElement('タグの名前');
```
- 子要素の末尾に要素を追加する
```javascript
親要素.append(追加する要素);
```
- 子要素の先頭に要素を追加する
```javascript
親要素.prepend(追加する要素);
```
- 要素を前と後ろに追加する
```javascript
指定要素.before(追加する要素);
指定要素.after(追加する要素);
```
- 要素を削除する
```javascript
削除したい要素.remove();
```
- 要素を置換する
```javascript
置き換えたい要素.replacedWith(置き換える要素);
```

## イベント
イベントとは、Webページ上で何らかの操作を行ったときに、それをシステムに知らせるもの。
- イベントを設定する
```javascript
要素.addEventListener(イベント名,関数名);
```
- イベントを削除する
```javascript
要素.removeEventListner(イベント名,関数名);
```
- イベントの種類
click：要素をクリックしたときに発生
input:フォームの入力欄にデータが入力されたとき、ラジオボタンを選択したとき、チェックボックスを選択したとき、セレクタを設定するとき発生
keydown,keyup：キーボードのキーを押したときに発生
mousemove,mousedown,mouseup：マウスの動かしたときに発生
scroll:画面をスクロールしたときに発生
- currentTarget,target
イベントが発生した要素を取得できる
currentTarget:addEventListenerを設定した要素
target:設定したイベントが発生した要素
- 規定の動作を停止
```javascript
イベントオブジェクト.preventDefault();
```
- 例
```javascript
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <button type="button">ボタン</button>
    <script>
      const button = document.querySelector('button');
      button.addEventListener('click',function() {
        console.log('クリックしました');
      });
    </script>
  </body>
</html>
```
【JavaScript】返り値がBooleanの場合でのスッキリとした書き方

## はじめに
- JS(TS)で`boolean`型で値を返す関数などをよく作成しているのですが、冗長な書き方をしていてスッキリと書ける便利な書き方を知ったので、使ってみたいと思います。

## 今回やること
- 実際に`boolean`型を返す関数を作成して、今まで書いていた冗長な書き方と便利な書き方を比較してみます。

## 前提(準備)
- JavaScript(TypeScript)で動かします。

## 実際にやってみる

- 今まで書いていた冗長な書き方
```TypeScript
function test(): boolean {  
  const testStr = ""
  
  if (testStr) {
    return true
  } else {
    return false
  }
}

console.log(test());
// false
```

- 今後使うスッキリ書ける書き方
```TypeScript
function test(): boolean {
    const testStr = '';
    return !!testStr;
}

console.log(test());
// false
```

※`Boolean()`を使う書き方でもよいみたいですが、今回紹介した二重否定のほうがシンプルだと思います。

## 終わりに
- 個人的にこのパターンは結構頻繁に出てくるので、良き発見でした！

## 参考
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Logical_NOT#%E4%BA%8C%E9%87%8D%E5%90%A6%E5%AE%9A_!!
【WordPress】投稿内の内部リンク一覧を好きな箇所に自動出力する方法（SEOにもオススメ）

# WordPress投稿内の内部リンク一覧を取得して、リスト出力するショートコードの作成方法

ブログの記事内に設置した内部リンクを自動で取得して、記事の最後に一覧で見れるようにしたら回遊率が上がるかなと思い、試しに実装してみました。
あくまで私のブログだけのデータですが、実際にブログ内に導入したところ回遊率が上昇したので、試してみたいという方はどうぞご利用ください。

実際に筆者のブログで利用しているコードです。（コピペ可）
```php:functions.php
// 内部リンクのリスト出力用ショートコード [my_shortcode_internal_links]
function my_internal_links() { 
	$content = get_the_content();
	$domain = $_SERVER['SERVER_NAME'];
	preg_match_all('/<a.+?href=".+'.$domain.'(?!.*#).*">.*<\/a>/', $content, $match);
	if($match):
		$match_unique = array_unique($match[0]);
		$html = '<section class="wp-block-post-content"><p>今回ご紹介した当ブログの記事はこちらです。</p><ul>';
		foreach ($match_unique as $link){
			$html .= '<li>'.$link.'</li>';
		}
		$html .= '</ul></section>';
		return $html;
	else:
		return;
	endif;
}
add_shortcode('my_shortcode_internal_links', 'my_internal_links');
```
実際の出力例を確認したい方は筆者ブログ【[ギフテッドブログ](https://gifted.blog/ "ギフテッドブログ")】の記事本文末尾でご確認可能です。

:::note info
重複したリンクは自動で１つにまとめており、テキストは投稿内のものをそのまま取得＆出力しています。
HTML箇所はご自由に変更可能です。CSSは各々で設定してご利用ください。
:::

:::note warn
上記コードはページ内リンク（#〜）が付いているリンクは除外して取得しております。
ページ内リンクも出力したい場合は下記内容に差し替えてご利用ください。
:::

### ページ内リンクも出力したい場合

```diff_php:functions.php
// ページ内リンクも出力したい場合は下に変更
-	 preg_match_all('/<a.+?href=".+'.$domain.'(?!.*#).*">.*<\/a>/', $content, $match);
+	 preg_match_all('/<a.+?href=".+'.$domain.'.*">.*<\/a>/', $content, $match);
```
下の行に差し替えるとページ内リンクもまとめて出力できるようになります。


## 利用方法
1. `functions.php` に上記コードを貼り付け。
2. テーマファイルの `single.php` または 投稿のブロックエディタ内に ショートコード `[my_shortcode_internal_links]` を貼り付け。
:::note info
`single.php`に貼り付ける場合は、ループ内に下記コードを貼り付けるとご利用できます。
`<?php echo do_shortcode('[my_shortcode_internal_links]'); ?>`
:::
Dapr 1.10のリリースハイライト

* Stepper workflow はビジネスロジックをマイクロサービス間でオーケストレーションするための新しいブロックです。

* Dapper はプラグイン可能なコンポーネント SDK を提供しており、任意の言語でプライベートコンポーネントを作成できます。

* 複数のマイクロサービスをローカルで実行するのは挑戦的であるため、Dapperでは「multi-app run」がリリースされました。

* Dapper 1.10でリリースされた新しいコンポーネントには、New Stage Stores、New Bindings、New Pub/Sub Brokersがあります。

https://www.youtube.com/watch?v=SZVNp9bWEu4
Daprは？

Daprとは、クラウドやエッジで動作し、様々な言語やフレームワークを採用することで、どの開発者でも強靭でステートレス・ステートフルなアプリケーションを簡単に構築できる、ポータブルでイベント駆動型のランタイムです。サイドカー アーキテクチャの利点を活用して、Daprはマイクロサービスの構築に伴う課題に取り組み、コードをプラットフォームに依存しないものにします。
flatpickr monthSelectPlugin を試してみる。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="LYJRVaj" data-user="remon11181986" style="height: 900px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/remon11181986/pen/LYJRVaj">
  Untitled</a> by remon11181986 (<a href="https://codepen.io/remon11181986">@remon11181986</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
JavaScirptの基礎まとめ 基礎編2～これは絶対に覚えておくべき～

# JavaScript 基礎編2
前回の記事は[こちら](https://qiita.com/shinry/items/c993981a0766100e4f6c)
JavaScirptの基礎まとめ 基礎編3は[こちら](https://qiita.com/shinry/items/06230d9d654245158ff0)

前回に引き続き基礎の内容をまとめようと思います。

## 関数
関数は処理をひとつにまとめることができ、定義した処理を呼び出すことで処理を実行する。
### 関数の基本
#### 引数と戻り値が存在しない場合
- 関数の定義
```javascript
function 関数名(){
  処理;
}
```
- 関数の呼び出し
```javascript
関数名();
```

#### 引数が存在する場合
- 関数の定義
仮引数は関数を定義する際の変数
```javascript
function 関数名(仮引数){
  処理;
}

//例
function welcome(name){
  console.log(`ようこそ、${name}さん`);
}
```

- 関数の呼び出し
実引数とは呼び出すときに実際に渡す値
```javascript
 関数名(実引数);

//例
welcome('Ryo');
```

#### 戻り値が存在する場合
- 関数の定義
```javascript
function 関数名(){
  処理;
  return 戻り値;
}
```
- 関数の呼び出し
```javascript
関数名();
```
#### 戻り値と引数が存在する場合
- 関数の定義
```javascript
function 関数名(仮引数){
  処理;
  return 戻り値;
}
```
- 関数の呼び出し
```javascript
関数名(実引数);
```

#### 引数を複数もつ関数
- 関数の定義
```javascript
function 関数名(仮引数1,仮引数2,仮引数3){
  処理;
}
```
- 関数の呼び出し
```javascript
関数名(実引数1,実引数2,実引数3);
```

#### デフォルト引数
仮引数を定義した関数で実引数を渡さない場合にデフォルトで値を設定する
- 関数の定義
```javascript
function 関数名(仮引数 = デフォルト値){
  処理;
}
```
- 例
```javascript
function welcome(name = 'ほげほげ'){
  console.log(ようこそ、${name}さん);
}

//例
welcome('Ryo');//ようこそ、Ryoさん
welcome();//ようこそ、ほげほげさん
```
### 関数の特殊記法
#### 関数式
関数式は処理を変数に代入して関数を定義する方法
- 関数式の定義
```javascript
const 変数名 = function(){
  処理;
  return 戻り値;
}

//例
const welcome = function(){
  console.log('ようこそ');
}

welcome();//ようこそ
```
#### アロー関数式
関数式を簡潔に書く方法
- 引数なしの場合
```javascript
// 通常の関数式
const sample = function(){
  処理;
}

// アロー関数式
const sample = () =>{
  処理;
}
```
- 引数ありの場合
```javascript
// 通常の関数式
const sample = function(x,y) {
  処理;
}

// アロー関数式
const sample = (x,y) =>{
  処理;
}
```

## オブジェクト
### オブジェクト
オブジェクトとは日本語で、ものや対象物という意味。
「人物」や「自転車」といった「もの」の情報の集まりをオブジェクトという。
```javascript
{
  キー1: 値1, //これひとつをプロパティという
  キー2: 値2,
  キー3: 値3
}

//例
const fruits = {
  name: 'バナナ',
  color: '黄色' ,
  taste: '甘い'
}
 
console.log(fruits);
```
- プロパティへのアクセス
```javascript
console.log(fruits.name);//ドット表記法
console.log(fruits['name']);//ブラケット表記法
```
- プロパティの追加と上書き

追加
```javascript
const fruits = {name: 'バナナ'}
fruits.color = '黄色';
fruits['taste'] = '甘い';
console.log(fruits);
//{name: 'バナナ',color: '黄色',taste: '甘い'}
```
上書き
```javascript
const fruits = {name: 'バナナ',color: '黄色'}
fruits.name = 'みかん';
furits['color'] = '橙色';
console.log(fruits);
//{name: 'みかん',color: '橙色'}
```
### メゾット
メソッドはオブジェクトの「振る舞い」を表したもの。
プロパティの値には関数が設定できる。プロパティの値に関数が設定されたものをメソッドという。
- メソッドの定義
```javascript
const オブジェクト名 = {
  プロパティ名：値,
  メソッド名: 関数式
}

//例
const person = {
  name: 'ボブ',
  age: '32',
  greet: function() {console.log('こんにちは');}
}
```
- メソッドの呼び出し
```javascript
オブジェクト名.メソッド名(実印数)

//例
person.greet();
```

## ブラウザオブジェクト
ブラウザオブジェクトでブラウザを操作する。
どこからでも呼び出せるグローバルオブジェクト。
- アラートを表示する
```javascript
window.alert('アラート');
alert('アラート');\\windowは省略できる
```
- 確認のダイアログを表示する
```javascript
confirm('これでokですか?');
```
指定した秒数後に実行する
```javascript
setTimeout(関数,ミリ秒数);
```
指定した秒数ごとに繰り返し実行する
```javascript
setInterval(関数,ミリ秒数);
```
### locationオブジェクト
locationオブジェクトはＵＲＬを操作することができる
```javascript
console.log(location.href);//現在のURLを表示
location.reload();//現在のページを再読み込みする
```
【Lion】Adamを超えたEvoLved Sign Momentum

## はじめに
Google Brainが2023年2月に出した最適化手法であるLionについての解説記事です。


- 論文
 
https://arxiv.org/pdf/2302.06675.pdf

- プログラム

https://github.com/lucidrains/lion-pytorch




## 結論(時間のない方向け)

- AdamWより収束速度が速い最適化手法であるLionを提案
- 画像分類、自然言語処理、拡散モデルでAdamWより高速かつ高精度を達成(一部問題設定ではAdamWと同等)

![ 2023-02-28 23.02.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/0dd7b84b-1f5e-ceec-0f41-6eb7a9609f2a.png)



## 手法
### 更新式
Lionの重みの更新式は以下である。

![ 2023-02-28 22.31.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/96c749a6-3002-0070-4351-5bdf4adf3f74.png)


(正則化項を無視すると) $\beta_1$を用いて計算した擬似的な慣性項($c_{t}$)の符号( $sign(c_t)$ ) の向きに重みを更新する。

$\beta_1 =0.9$、$\beta_2 =0.99$であり、符号計算に用いる擬似的な慣性項( $c_{t}$ )よりも慣性項( $m_{t}$ )の方が過去の勾配情報を多く記憶している。

また上図ではAdamWと同様に正則化項( $\lambda \theta_{t-1} $ )を加えている。

### 動機
Lionは**最適化手法自体を進化的に探索すること**で得られた。

詳細は2章(2.2、2.3節)で述べらており、以下のPrigram 8から進化的な探索によってLionを得た。

![ 2023-03-01 0.02.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/10dc450f-8f84-17c0-39ee-8dbf306a6be4.png)


### AdamWと比べた優位点
比較対象のAdamWの重み更新式は以下である。

![ 2023-02-28 22.50.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/01bdc28d-9aa0-023c-fcdd-a6fed3ebfc6d.png)

AdamWでは勾配の二乗を指数減衰させた項( $\nu$ )を用いているため、Lionの方がメモリ効率がよく、計算時間が短くなる。

したがってLionでは大規模モデルや大きいバッチサイズでの学習で有利である。

## 実験
### データセット(画像分類のみ)
- ImageNet系(ImageNet, ImageNet ReaLなど)
- ObjectNet
- CIFAR100
- OxFord-IIIT Pet

### モデル(画像分類のみ)
- ViT系


他にも対照学習、自然言語処理、拡散モデルで
実験をしている。


## 結果
画像分類、対照学習、自然言語処理、拡散モデルでAdamWより高速かつ高精度を達成した。(一部問題設定(後述)ではAdamWと同等)



### 画像分類の結果
学習速度、精度の観点からAdamWよりも優れる。


![ 2023-02-28 23.14.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/8840e040-b50c-5f4a-4f4f-fe8572bf07d2.png)

![ 2023-02-28 23.52.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/4718fd24-d3fc-e86e-f1c8-e1e4ad66f6e7.png)

![ 2023-02-28 23.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/76ae376e-49be-42c9-bbc0-c28feab9592b.png)

![ 2023-02-28 23.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/0e46a198-4876-a27f-fe61-52f44842948b.png)


### AdamWと同等の結果
専門外の分野も混じっていて誤訳が怖いので原文を載せる。

- the Imagen text-to-image base model  (テキストから画像を生成するモデル)
-  the perplexity of autoregressive language model trained on the large-scale internal dataset, which is arguably a more reliable metric the in-context learning benchmarks 
-  masked language modeling on C4

これらのタスクは、データセットが大規模かつ高品質であるため、最適化手法間の差異が小さくなる。



## 筆者の所感
- 慣性項の向きだけで重みを更新した方がAdamよりも優れている点については、最適化手法を研究している自分からしても驚きである一方で納得はできる
- だが学習データの品質に依存していそう(データ間で勾配情報の絶対値の差が大きい場合など、LionだとAdamに負けそうだが？)
- SGDとの比較をして欲しかった。多分精度面で負けたはずなので、載せてないと思うが。
- 実験結果の量はさすがGoogle、リソースがエグすぎる。。。
如何把jQuery得的值与PHP分享（1）

大家好！我是Juesa09。

这几个月没力气出门，周末一般都在家发呆，总觉得白白挥霍时间。所以想做个东西，让自己化解这个烦闷心情。

最近做的是在家迷你娱乐场游戏（Mini Casino）。就像澳门casino的骰宝游戏。
玩法简单说明一下，把钱赌给你猜骰子会开的数字，骰子一共有三个，只要有一个以上的骰子猜中就赢。返回的利益是依猜中的骰子的数量增加。一个就双倍，两个就三倍，三个就四倍。

作的画面是如下。先选择骰子数字和输入金额后按“赌”，然后再按“掷骰子”就开始。
按“停止”就停。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120035/cdefbf7c-1bbc-45c8-5a58-63f9c791eb3a.png)


其实这个基本的操作画面是两年前作的。这次我进一步修改了功能。
要用RFID（读卡模式）来管理每一张卡的信息。

每一张卡片都有它唯一的卡号。把卡号读取后往Database（My SQL）去查询它所绑定的用户名、余额、最后玩的时间。

编程的时候最伤脑筋的是如何把jQuery得的值发给PHP。
但后来发现这两个被执行的地方完全不一样，根本无法传送。

所以我用hidden的HTMLtag来解决这个问题。
下次我会用实际的code来和大家分享一下具体的操作。

今天就聊到这里。
下次见！
vscode.window.withProgress()を使った拡張機能を呼び出すときに気をつけること

# はじめに

`vscode.window.withProgress()`を呼び出すコマンドをテストしたときに、それは発生した。

# TL;DR

`await`を忘れずにつけよう。

# テキストを挿入しても内容が更新されない問題

前提として、`withProgress()`に渡すコールバックの中で、非同期関数を呼び出していた。
そして、その非同期関数を呼び出した後、アクティブなエディタを取得して、選択したテキストの末尾に生成したテキストを挿入していた。

```ts
vscode.window.withProgress(
	{
		location: vscode.ProgressLocation.Notification,
		...
	},
	async (progress, token) => {
		return new Promise(async (resolve) => {
			...
			const messages = await Promise.all(...);

			await editor?.edit((textEditor: vscode.TextEditorEdit) => {
				for (const index in selections) {
					const selection = selections[index];
					const text = texts[index];
					const message = messages[index];
					if (selection && text) {
						textEditor.insert(selection.end, "\n" + message);
					}
				}
			});
			resolve(null);
		});
	}
);
```

これを次のようにテストしたところ、`openTextDocument()`を呼び出した際に渡した`content`の値から変化せず、`strictEqual()`が失敗に終わった。

```ts
const document = await vscode.workspace.openTextDocument({
  content: selectedText,
});
...
await vscode.commands.executeCommand("extension.command");
...
assert.strictEqual(
  document?.getText(),
  `${selectedText}${newCOntent}`
);
```

# `await`のつけ忘れ

これは自分の凡ミスなのだが、結局のところ`await`のつけ忘れだった。

```ts
await vscode.window.withProgress(
	{
		location: vscode.ProgressLocation.Notification,
		...
	},
    ...
);
```

# `await`をつけ忘れた理由

参考にしていたコードでは次のように`withProgress()`を呼び出していた。

```ts
return vscode.window.withProgress(
	{
		location: vscode.ProgressLocation.Notification,
		...
	},
    ...
);
```

ただ、僕の場合はこのコードを呼び出し後も処理を行う必要があったため、`return`をつけずにそのまま呼び出していた。
デバッグ時にはこの問題に気づかなかったため、テストをしたときに初めて気がついた。

# まとめ

`vscode.window.withProgress()`を呼び出すときは必ず`await`のつけ忘れを確認しましょう。（`return`する場合は除く）
あと、テストはきちんと書きましょう。デバッグだけでは気づかない問題に出会うことができます。
GitHubに草を生やす

# 【GitHub】に草(コントリビューション)を生やそう！

プログラミング初心者やってしまいました…
8月から2月の途中までほぼ真っ新……
気が付いてはいたのですがポートフォリオに夢中で、調べるのを後回しにしてしまっていました。
単純なミスだったので、後回しにしたことをほんとに後悔してます:sob:
ほぼ毎日頑張ってきたのに真っ白.....
また同じミスをしないように、やり方を記録していきたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/8057469e-607e-1f7e-743f-f7fcffddb83b.png)

こんな感じで後半は訂正し、草を生やし続けられています。



# 草の生やし方(初回版)
初めてGitHubにプッシュするよ～っていう場合のやり方

①git initはリポジトリを新規作成するコマンドです。
バージョン管理をしていない既存プロジェクトをGitリポジトリに登録するときや、新規リポジトリを作って開発を始めるときなどに使います。
```php
$ git init
```
②ワークツリーとインデックスの状態を確認するコマンドです。
```php
$ git status
```
③

```php
$ git add ファイル名  # 「$ git add .」 で一括で選択できる
```

④コメントは
何をどの様に変更したか追加したかを書く。
誰から見てもどこが変わったか分るように。

```php
$ git commit -m "コメント"
```
⑤ローカルリポジトリとリモートリポジトリを紐づける

```php
$ git remote add origin リポジトリURL
```

↑を忘れてたから草生えてなかったみたい…
大事ですこれ
全部大事なんですけどね…

⑥masterブランチをmainブランチに変更する

```php
$ git branch -M main    # ブランチ名をmasterからmainに変える
```

⑦リモートリポジトリへPushする

```php
$ git push origin main
```


# 2回目以降

```php
$ git status
```

```php
$ git add ファイル名     # 「$ git add .」 で一括で選択できる
```

```php
$ git commit -m "コメント"
```

```php
$ git push origin main
```


同じミスしないように気を付けたいと思います！
【Zsh】先の日時を出力する方法

## 先の日付を取得する方法
1日後の日時を取得するには以下のように実行する。

```zsh
date -v+1d
```

```zsh
$ date
2022年 9月25日 日曜日 19時35分23秒 JST

% date -v+1d
2022年 9月26日 月曜日 19時36分00秒 JST
```
JetpackComposeで、Drawerを右から出す

JetpackComposeでは、NavigationDrawerのようなものが提供されている。
Scaffoldでも引数で指定可能だが、もう少し奥まで読むとModalDrawerというもので提供されている。
これは標準では（一般的なLocaleでは）左から出る。これを右から出したい。

本記事ではDrawerの開閉方法については触れず、右から出す方法にだけ注目して記述します。

やることは３つ。
1. CompositionLocalProvider を使って、LayoutDirectionを右からに変更する
2. 表示するコンテンツも右寄せになってしまうので、CompositionLocalProviderで左からに上書きする
3. Shapeを指定して、中のコンテンツの横幅だけを表示するようにする

<img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85214/02231c35-a5b5-5e18-5eb0-ea8c48c26c81.png" />


## 1. CompositionLocalProvider を使って、LayoutDirectionを右からに変更する

Scaffoldを例に記述する

```kt
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
        ) {
            ...
        }
    }
```

## 2. 表示するコンテンツも右寄せになってしまうので、CompositionLocalProviderで左からに上書きする

```kt
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
            drawerContent = {
                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                    // Drawerの中身
                }
            },
        ) {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                // 本体
            }
        }
    }
```

## 3. Shapeを指定して、中のコンテンツの横幅だけを表示するようにする

```kt
　　　　　　　　val EndDrawerPadding = 56 // ModalDrawerの中で指定されている、Drawer余白の固定値(dp)
　　　　　　　　val DrawerWidth = 100 // dp
    val configuration = LocalConfiguration.current

    fun customShape() = object : Shape {
        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density
        ): Outline {
            val screenWidth = with(density) { configuration.screenWidthDp.dp.toPx() }
            val drawerContentWidth = with(density) { screenWidth - EndDrawerPadding.dp.toPx() }
            return Outline.Rectangle(
                Rect(
                    drawerContentWidth - with(density) { DrawerWidth.dp.toPx() },
                    0f,
                    screenWidth, // drawerContentWidthを指定すると少し余白ができちゃうので、多めに指定している
                    with(density) { configuration.screenHeightDp.dp.toPx() }
                )
            )
        }
    }
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
            drawerShape = customShape(),
            drawerContent = {
                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                    // Drawerの中身 （例）
                    Column(modifier = Modifier.size(DrawerWidth.dp)) {
                        // ...
                    }
                }
            },
        ) {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                // 本体
            }
        }
    }
```

## 懸念

EndDrawerPadding はModalDrawer内で定義されているPrivateスコープの値だけど、これがアップデート変わったら死ぬ＾＾
BigQueryでスプレットシート読み込み時にAccess Deniedエラー

[https://developers.google.com/apps-script/advanced/bigquery?hl=ja#run_query](https://developers.google.com/apps-script/advanced/bigquery?hl=ja#run_query)

上記チュートリアルに従ってGoogle Apps Script(GAS)を使ってBigQueryにアクセスしようとしたところ以下のエラーが発生しました。

> GoogleJsonResponseException: API call to bigquery.jobs.query failed with error: Access Denied: BigQuery BigQuery: Permission denied while getting Drive credentials.
> 

## 解決方法

以下の方法で解消できました。

1. GASの*[サービス]*で Google Drive API を有効にする
![スクリーンショット 2023-03-20 23.24.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169464/e8ca22ae-e638-f33b-6ad4-66b0adeb7dc0.png)

2. `DriveApp.getRootFolder();`を関数の先頭に追加して、Drive Auth Scope を取得。
```javascript
function runQuery() {
  DriveApp.getRootFolder();
  ...以下略
```
zshについて

# はじめに

#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>


# zshとは何か

zsh(ズィーシェル)と言います。shell(シェル)の１つです。


OSとアプリケーションの間に立ち、ユーザーからの要求をシステムに伝えるためのユーザーインターフェースです。

コマンドを入力することで動くプログラムのことをシェルといいます。

zshはsh、bash、csh、tcshの機能をほぼ網羅しているシェルです。


# シェルの特徴



ログインシェルと非ログインシェルがあります。ログインシェルは、UNIX系OSにログインした時点で適用されるシェルのことです。


非ログインシェルは、UNIX系OSにログインしてから任意に適用するシェルのことです。



# まとめ    


Macではデフォルトにbashを採用していましたが、


Catalina世代からデフォルトシェルをzshに変更したようです。


シェルが違うと環境変数などの設定ファイルが異なってきますので注意が必要です。
N + 1問題とは

## はじめに
N + 1問題については、とても参考になるまとまった記事がたくさんあるのですが、自分なりに簡単にまとめてみました。解釈が間違っていましたらご指摘ください。

## N + 1問題とは
簡単に言えば、SQLを重複して発行してしまうこと。

例えば投稿アプリで投稿一覧ページがあった場合にユーザーの名前を表示したい場合
```ruby:post_controller.rb
def index
  @posts = Post.all
end
```
```erb:post_index.erb
<% @posts.each do |post| %>
  <%= post.user.name %>
<% end %>
```
のようにすると思います。
この場合発行されるSQLは以下のようになります。
1. `@posts = Post.all`で投稿を全て取得
2. `post.user.name`で投稿に紐づくユーザーを取得

2.の、投稿に紐づくユーザーを取得するとき、画面に表示される投稿の数分、投稿に紐づくユーザーを一回一回SQLを発行して取得してきます。

つまり投稿が10件の場合、まず`Post`を全て取得するSQLと、投稿の数分(N)のSQLが発行されることになり、これが「N + 1」問題と呼ばれています。

これではデータの数が多いほど、パフォーマンスが低下するのは明白です。
そのため、N + 1問題が起きてしまった場合は`preload`メソッドか、`eager_load`メソッドを使用することで解決します。

## preload
`preload`メソッドを使用して引数にアソシエーションを渡すことで、Postのデータとともに関連するuserのデータも取得してくれます。
SQLの発行回数は、Postのデータ取得で1回、Postに関連するuserの取得で2回となります。
```ruby:post_controller.rb
def index
  @posts = Post.preload(:user)
end
```
## eager_load
`eager_load`メソッドも、同様にアソシエーションを取得してくれます。
こちらはテーブル同士を一つに結合させてしまい、viewで呼び出す際にその結合したテーブルから得たデータを取得します。
SQLは1回だけです。
```ruby:post_controller.rb
def index
  @posts = Post.eager_load(:user)
end
```

## どちらがいいのか
調べてみた感じでは、「こっちを使った方がいい」というような偏った意見は見かけませんでした。
テーブルを結合させるのかさせないのかなど、アプリが複雑で大規模なものであれば考える必要がある印象です。個人開発であれば取り敢えず`eager_load`メソッドを使っておけばいいのかな？と思います。

## 参考
[ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い](https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58)
[【Ruby on Rails】n+1 問題とは?](https://qiita.com/seiyatakahashi/items/37bef984168b9f1ce25e)
ElixirDesktopのサンプルアプリをサクッと動かす

## Elixir Desktopとは

Phoenix LiveViewを使って、ネイティブアプリのようなElixirアプリを作成できるパッケージです。

> Building native-like Elixir apps for Windows, MacOS, Linux, iOS and Android using Phoenix LiveView!

https://github.com/elixir-desktop/desktop

## さっそくサンプルアプリを動かしてみる

### サンプルアプリをgit cloneする

https://github.com/elixir-desktop/desktop-example-app

### 依存関係をインストールする

```zsh
cd desktop-example-app
mix deps.get
```

### サンプルアプリのリポジトリ通り、アセット関連のコマンドを実行する

```zsh
cd assets
npm install
cd ..
mix assets.deploy
```

### ルートディレクトリにあるrunファイルを実行

```zsh
./run
```

### 動きました！マル！

![スクリーンショット 2023-03-20 22.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/46b2d83a-8ab2-d60f-fc55-57b1c500b817.png)

デスクトップ版は特にハマることなく動きました:ok_hand:
CharlesでiOSのアプリケーションの通信を覗いてみる


## やりたいこと
ネイティブアプリケーションで叩いているAPIをCharlesで覗きたい


## こんな人向け
・ 開発中のアプリがVPNを経由しないとAPIを叩けない
・ ネイティブアプリでAPIの中を覗きたい
・ Charlesを使ってみたけど、**VPNを経由して覗く方法が知りたい**


では、やっていきます！


## 事前準備
Charlesが使用できる様に、初期設定を終わらせましょう！  




【参考文献】

https://qiita.com/ishigaki_hige/items/cf86d35e13470a543551


https://eda-inc.jp/post-3926/




## 必要なもの
・ CharlesがインストールされているPC
・ そのPCがVPNに接続できる状態であること
・ iPhone
・ Wi-Fi


## 作業手順

### ① PCとiPhone端末を同じWi-Fiに接続します
とても大事です。ここが原因で接続できないミスもありますので、しっかり確認していきましょう
また、「自動的にVPNに接続されてしまうWi-Fi」にも注意しましょう
**VPNに接続しない状態で**、同じWi-Fiに接続します  

### ② Charlesを起動します
何度も言いますが、**VPNに接続していない状態で**起動します


### ③ プロキシとなるIPアドレスをメモします
Charlesを開いている状態で、
メニューバーにある **Help > Local IP Addresses** を押下し、IPアドレスをメモします
後ほど使用します。

![スクリーンショット 2023-03-20 22.09.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1422262/e27fb1c4-1e1d-8dd6-90d0-bbf0a3747bc1.png)



### ④ iPhone側の設定をしていきます
iPhoneの **設定 > Wi-Fi > 「PCと同じWi-Fi」のℹ️マーク**　をクリックします
画面一番下までいき、　**HTTPプロキシ > プロキシを構成** をクリックします

この辺の遷移については、以下の記事をご参考に辿り着きましょう...！！

【参考資料】

https://kyoto-hirota.com/iphone%E3%81%A7proxy%E8%A8%AD%E5%AE%9A%E3%81%AE%E6%96%B9%E6%B3%95%E3%82%92%E8%AA%AC%E6%98%8E%E3%81%97%E3%81%BE%E3%81%99%E3%80%82/


### ⑤ 「手動」をクリックします
手動をクリックして、下記の情報を入力し、「保存」をクリックして画面を閉じてください

サーバー： 手順③で控えていたIPアドレスを入力します
ポート： 初期設定でCharlesに登録してあるポート番号を入力します。多分8888になっているでしょう



### 一旦休憩
今やったことは、「**PCをHTTPプロキシとして登録**」しました。
本来であれば、iPhoneがSafariを開く、Youtubeを開くなど、iPhoneが直接通信しますが
**その通信をPCが代理で行う**ということです。

つまり、iPhoneでAPIを叩いても、その通信はPCが行なっている様なイメージです
（イメージです）

ここまで言えばわかりますよね...？
APIを叩く際にVPNが必要であれば、
**PCがVPNに繋がっていれば、iPhoneはVPNに接続しなくてもAPIが叩けます**

では続きをやっていきましょう


### ⑥ PCをVPNに接続します
注意：Charlesを起動している状態で、VPNに接続しましょう。
VPNに繋いでいる状態でCharlesを起動すると、うまくいかないことがあります。

https://www.charlesproxy.com/documentation/faqs/vpn-not-working-with-charles/


### ⑦ iPhoneでネイティブアプリを起動し、動作確認をします
これで設定は終わりです。
正しくAPIが覗けるかCharlesで確認してみましょう。
きっとうまくいっているハズです





## やりがちなミス
・ iPhoneからVPNに接続する必要はありません。何度も言います
・ Charlesを起動してから、VPNに接続してください。
・ 初めてCharlesと接続する際、「このデバイスと接続しますか？」　=> 「allow or deny」
　と警告モーダルが出ますが、**必ずallowにしてください**。
・証明書のインストールや信頼にする設定は飛ばさずに必ず実行してください


だいたいこの辺のミスを潰していけば接続できると思います...



以上で、今回の説明は終わりです！
最後に、Charlesでハマりやすいポイントの参考資料を残しておきます。
業務上載せられない情報が多く、文字ばかりですみません。
みなさまもうまくいくことを祈っております


https://qiita.com/ayakix/items/3a199a991382b482894c
【PAD】WebページでJavaScript関数を実行で関数を書きたい。

# WebページでJavaScript関数を実行で、関数を書きたい。

PowerAutomateDesktopを使って、DOMにアクセスしたいときWebページの要素にマウスをポイントなどでUI要素を使うことが多いかもしれませんが、私はコード書いたほうが早いなと思うときが多いです。笑
たびたび、「WebページでJavaScript関数を実行する」を使います。ただ、for of文やfetchAPIなどが使えない制約があります。
関数も、ExecuteScriptの中で書かないといけないらしく、ネットであまり情報もなかったので投稿しました。

### うまくいった書き方
```
function ExecuteScript() 
{ 
	function test() {
		alert('test関数の中だよ!');
	}
	test();
	return;
}
```

他の書き方もあったら教えてください。
Ubuntu: find の使いそうなコマンドまとめ

# 背景
Libがどこにあったっけ？とか、*.so ファイルの実態どこ？とか、先週触ったファイルどこだっけ？
なんて時用に

普通は、name, mtime, mmin 程度で事足りる

# コマンド一覧

| オプション | 引数 | 説明 | 利用例 | 利用例の説明 |
| --- | --- | --- | --- | --- |
|name|string|ファイル名検索|find . -name "libc10*.so" | libc10_cuda.so みたいなファイルを検索|
|type    | f, d, ...  | ファイルタイプ（f:通常ファイル, d:ディレクトリなど）  | find . -type f| カレントディレクトリ以下の通常ファイルを検索 |
|maxdepth| n 　| 検索する階層（n:階層数）　| find . -maxdepth 1 -name "*.txt"　| カレントディレクトリ直下のtxtファイルを検索 |
|mtime     |n     |最終更新時間 ( n : 日) | find . -mtime +7 -name "*.txt" |更新時間が7 日以上前の txt ファイルを検索|
|mmin      |n     |最終更新時間 ( n : 分) | find . -mmin +60 -name "*.txt" |更新時間が60 分以上前の txt ファイルを検索|
|atime     |n     |最終アクセス時間 ( n : 日) |find . -atime +7 -name "*.txt" |-クセス時間が7 日以上前の txt ファイルを検索|
|amin      |n     |最終アクセス時間 ( n : 分)  　| find . -amin +60 -name "*.txt"  　|アクセス時間が60 分以上前の txt ファイルを検索|
|ctime     |n     |最終変更時間 ( n : 日)  　|find . -ctime -1 -name "*.txt"  　|変更時間が1 日以内の txt ファイルを検索|
|cmin      |n     |最終変更時間 ( n : 分)  　|find . -cmin -60 -name "*.txt"  　|変更時間が60 分以内の txt ファイルを検索|


- type のオプション
f: 通常ファイル
d: ディレクトリ
c: 文字デバイスファイル
b: ブロックデバイスファイル
p: 名前付きパイプ（FIFO）
l: シンボリックリンク
s: ソケット

-  GNU find
D: ドア (Solaris)
F: ファイルシステム境界を示すファイル (macOS)
L: シンボリックリンク（シンボリックリンク先も検索対象）
P: 名前付きパイプ（FIFO）またはソケット
S: ストップされたプロセスによって開かれたファイル (macOS)
W: ホワイトアウト (FreeBSD)
X: 拡張属性を持つファイル (macOS)

# あとがき
ん－、GUI に毒されてるんだろうけど、AI 秘書欲しい
Bootstrap5のモーダルウィンドウをJavaScriptで制御する

[Bootstrap5のモーダル](https://getbootstrap.jp/docs/5.0/components/modal/)を連動しているボタン以外で制御したかったが、古いバージョンの情報だったりclassをJavaScriptで上書きするだったりと、よくわからないやり方しか見つからなかったので書く。

## やりたいこと
Bootstrap5のモーダルウィンドウをエラーダイアログ的なノリで使いたい。
`data-bs-toggle`とか`data-bs-target`が着いてるボタンで制御するのではなくて、JavaScriptで制御して他の処理との流れで開閉したい。

## 環境
- Bootstrap：5.0.2



## やりかた
対象のモーダルのエレメントを引数にモーダルのインスタンスを作成し、そこから`show()`や`hide()`といったメソッドを呼び出すだけ。
※BootstrapのJavaScript必須
```javascript:controlModal.js
const myModal = new bootstrap.Modal(document.getElementById('myModal'));
// 開く
myModal.show();
// 閉じる
myModal.hide();
```

## サンプル
inputでファイルが選択されていなかったらモーダルダイアログを出すサンプルです。
html1枚でできているのでコピーして動作確認してみてください。
```html:modal.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- BootstrapのCSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <title>モーダルをJavaScriptで制御</title>
</head>
<body>
  <div class="container">
    <!-- メインコンテンツ -->
    <div class="mb-3 w-50">
      <label for="formFile" class="form-label">モーダルのテスト</label>
      <input class="form-control" type="file" id="formFile">
      <button id="upload" class="btn btn-primary">アップロード</button>
    </div>
    <!-- エラーダイアログ用のモーダル（id重要） -->
    <div class="modal fade" id="errorModal" tabindex="-1" aria-labelledby="errorModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="errorModalLabel">エラー</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            ファイルが選択されていません
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">閉じる</button>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- BootstrapのJavaScript（先に読み込む） -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  <!-- モーダルをコントロールするJavaScript -->
  <script>
    // input読み取り用
    const inputFile = document.getElementById('formFile');
    const uploadBtn = document.getElementById('upload');
    // エレメントを引数にしているのがポイント
    const errorModal = new bootstrap.Modal(document.getElementById('errorModal'));

    // ボタンがクリックされたら～っていうよくある処理
    uploadBtn.addEventListener('click', () => {
      const input = inputFile.files[0];
      if (!input) {
        // ファイルが選択されていなかったらモーダルを開く
        errorModal.show();
      } else {
        // 通常処理（今回は何もなし）
      }
    });
  </script>
</body>
</html>
```
## おわりに
私はこの情報に辿り着くまでにまあまあ時間を使ってしまったので、そういう人が減るといいなと思います。
AIにフリー素材の人物画像を学習させていろんな画像を生成する

# 自分好みのフリー素材画像を作る
![00049-1383593218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/b96ef2e6-22e2-be56-5f75-6ad9aabc2d10.png)

**フリー素材の画像って便利ですよね。**
商用利用できるので、自分のサイトやアプリや広告に使える。
こういう画像↓
![takaomiudsc_0171-2769_TP_V.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/279e647b-7b52-9d30-e2fc-f0a861984738.jpeg)

でも、**フリー素材の画像には限りがあるので、なかなか自分が欲しい画像を見つけられなかったりもします。**
この人物がオレンジジュースを飲んでいる画像が欲しいのにそんな画像は存在しない、みたいな。
そこで、**今回はすでにあるフリー素材の人物からAIを使ってその人物の全く違う画像を生成します。**

# 手順
### 1.ある人物の画像を集める
今回は、[ぱくたそ](https://www.pakutaso.com/)というフリー素材のサイトから、このモデルさんの画像を集めました。53枚です。
名前は存じ上げませんが、仮に「ぱくたそちゃん」にします。

![スクリーンショット 2023-03-20 16.59.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/309882e5-fe76-3079-2eaf-1e703be253b2.png)


### 2.AIにその人物の画像を学習させる
この「ぱくたそちゃん」の画像をAIに食わせます。
最初は似てるんだか似てないんだかわからない状況ですが、だんだん学習していきます。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/5bf568d7-43ff-edbc-e1fa-3eee264c6bf6.png width=400> <img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/48ef5c87-4470-b822-275d-96f9a89e92d3.png  width=400> 


### 3.欲しい画像を説明するテキストを入力して、その人物の全く新しい画像を生成する
**「ぱくたそちゃん」「カメラ目線」「黒髪」**
![00032-3454515305.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/6e09bfd3-2012-0973-5843-1427b5c19121.png)
**「ぱくたそちゃん」「オレンジジュースを飲む」**
![00049-1383593218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/76f7043e-1b18-b600-732b-c715709f712f.png)

トレーニング時間が短くてちょっと似ているという程度ですが、この顔のテイストをベースにいろんな画像が生成できます。
例えばオレンジジュースの広告とか、自分の使いたい用途に合わせて画像を作れます。


# プログラミングの手順
### 0.StableDiffusion-WebUIをインストールして起動
https://github.com/AUTOMATIC1111/stable-diffusion-webui

(参考：)

https://qiita.com/john-rocky/items/1b6dd780d38c63bb64cd

### 1.画像データを集める
### 2.StableDiffusion-WebUIで学習設定して学習開始
##### ・画像データに対応する単語を決める
今回は「pakutasochan」 という単語を対応させます。

![スクリーンショット 2023-03-20 15.48.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c8cb4489-1b84-10f0-5f7e-cf837bc784ea.png)

##### ・画像の前処理を行う
保存先に前処理を行った画像が保存される
![スクリーンショット 2023-03-20 15.51.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7bc11eeb-da35-aa31-d5da-acdd7f54f179.png)

##### ・画像ディレクトリを指定して学習開始
![スクリーンショット 2023-03-20 15.51.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/542dd3c2-847a-bb6c-849e-11464ead572b.png)

### 3.生成
学習の結果保存されるpakutasochan.ptというpakutasochanというテキストのベクトルをstable-diffusion-webui/embeddingsフォルダにおいてwebUIを再起動し、テキストを入れて生成します。

🐣
****
フリーランスエンジニアです。
もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
CakePHP4でusers Tableへ別々に保存した姓と名を結合して、ニックネームと同時にLike検索する

baserCMS5ではユーザテーブルに名前に関する情報として、姓と名とニックネームカラムがあります。
姓と名は結合して検索したいよねって場合もよくありますよね。

そんなときは下記みたいなコードで取得することができますよ。

```
$concat = $query->func()->concat([
    'Users.real_name_1' => 'identifier',
    'Users.real_name_2' => 'identifier',
]);
$query->where(function ($exp) use ($concat, $keyword) {
    return $exp
        ->setConjunction('OR')
        ->like('Users.nickname', '%' . $keyword . '%')
        ->like($concat, '%' . $keyword . '%');
});
```
Salesforce フローからメールを送ったログを活動タイムラインに記録する

# やりたいこと
[拡張メール機能](https://help.salesforce.com/s/articleView?id=sf.enable_enhanced_email.htm&type=5)を使うとSalesforceから送信したメールは活動タイムラインに記録されますが、フローからメールを送るとそれが記録されません。
フローからメールを送ったときでも活動タイムラインに送信ログが残るように設定していきます。
# 設定内容
全体の流れとしてはフローでアクションを使ってメールを送信した後、EmailMessageとEmailMessageRelationに直接レコードを生成することで活動タイムラインに載るようにします。

## 1. メールを送信する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/a6c050fb-786c-60ee-8a01-ba13f5719fbb.png" width="500">


## 2. EmailMessageオブジェクトにレコードを追加する
今送ったメールの内容をそのままEmailMessageオブジェクトにinsertする。
このとき作成したレコードIDを次のEmailMessageRelationオブジェクトのinsertの時に使用するため`手動で変数を割り当て`にチェックを入れてレコードIDを保持しておく。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/0c3b052d-3b48-55bc-a2d1-09d1cad3f938.png" width="500">

## 3. EmailMessageRelationオブジェクトにレコードを追加する
2で取得したレコードIDを`EmailMessageId`に、活動タイムラインと紐付けたいリードや取引先責任者のレコードIDを`RelationId`に渡す。
RelationTypeは以下の選択肢の中から、リードや取引先責任者がメールメッセージと持っている関係性がなんなのかを定義する。
- ToAddress
- CcAddress
- BccAddress
- FromAddress
- OtherAddress
今回の場合はContactへのメールをToで配信してそのリレーションを持つという想定のためToAddressを選択。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/5690c8da-de7f-4f0e-18a3-39c93703013f.png" width="500">

# 完成
これで無事に活動タイムラインにフローからのメール送信ログを残せるようになりました。
この処理を直接書かなくても自動で記録されるようになるといいなぁ。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/03146e10-a5ff-2732-0b4a-4229c79810ff.png" width="300">

メール送信の処理を入れる都度、この処理を書き加えるのはナンセンスなので、この部分だけ切り出してサブフローにしておいた方が良いかもしれません。
[python3] loggingのタイムスタンプを変更する

pythonのloggingでは、ログのタイムスタンプは `time.time()` で生成されるのですが、 `time` モジュールで使用可能なディレクティブの関係でタイムスタンプの形式に制限があります。
なので、 `datetime` を使ってISO8601などに変換できるようにします。

（参考）  
`logging` モジュールでは以下でミリ秒を後から付け足す形で整形していますが、ここでは書式化演算子（ `%` ）を使っています。  
https://github.com/python/cpython/blob/v3.11.2/Lib/logging/__init__.py#L630  
ミリ秒は独自で計算されている様子。  
https://github.com/python/cpython/blob/v3.11.2/Lib/logging/__init__.py#L337


## ISO8601にする

ハンドラにフォーマットを設定する時に、 `logging.Formatter` クラスの `formatTime()` をカスタムしたものを使用すればできます。  
`record.created` にタイムスタンプがUNIX時間（typeはfloat）で格納されています。

```py
import logging

from datetime import datetime, timedelta, timezone


class ISOTimeFormatter(logging.Formatter):
    def formatTime(self, record: logging.LogRecord, datefmt=None):
        tz_jst = timezone(timedelta(hours=+9), 'JST')
        ct = datetime.fromtimestamp(record.created, tz=tz_jst)
        s = ct.isoformat(timespec="microseconds")

        return s


logger = logging.getLogger()
fmt = ISOTimeFormatter("%(asctime)s - %(message)s") # logging.Formatterの代わりに自作のクラスを使う

sh = logging.StreamHandler()
sh.setFormatter(fmt)
logger.addHandler(sh)

logger.setLevel(logging.INFO)
```

あとは `logger.info('hello')` などで出力するだけです。 `%(asctime)s` がそのままISO8601のタイムスタンプになります。

```
2023-03-20T21:01:22.279373+09:00 - hello
```


## その他の書式にする

ほとんど同じ要領ですが、 `logging.Formatter` は `datefmt` を指定することができるので、以下のようにしてもよいと思います。

```py
import logging

from datetime import datetime, timedelta, timezone


class DatetimeFormatter(logging.Formatter):
    def formatTime(self, record: logging.LogRecord, datefmt=None):
        if datefmt is None:
            datefmt = "%Y-%m-%d %H:%M:%S,%03d" # logging.Formatterのデフォルトと同じ形式

        TZ_JST = timezone(timedelta(hours=+9), 'JST')
        created_time = datetime.fromtimestamp(record.created, tz=TZ_JST)
        s = created_time.strftime(datefmt)

        return s


logger = logging.getLogger()
fmt = DatetimeFormatter("%(asctime)s - %(message)s", datefmt="%Y-%m-%dT%H:%M:%S.%f%z") # ここでフォーマットを指定する

sh = logging.StreamHandler()
sh.setFormatter(fmt)
logger.addHandler(sh)

logger.setLevel(logging.INFO)
```

出力すると以下のようになります。

```
2023-03-20T21:11:27.637558+0900 - hello
```


## 参考

- [timeモジュールで使用できるディレクティブ](https://docs.python.org/ja/3/library/time.html#time.strftime) 
- [datetimeモジュールで使用できるディレクティブ](https://docs.python.org/ja/3/library/datetime.html#strftime-and-strptime-format-codes)
【JavaScript】JavaScriptまとめ①

# 概要
JavaScriptの理解を深めるため、
[<img width="200" alt="51vlB3JskRL.jpg" src="https://m.media-amazon.com/images/I/41vZUGXaYML._SX350_BO1,204,203,200_.jpg">](https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8BJavaScript-%E6%96%B0%E7%89%88-%E6%A1%9C%E5%BA%AD-%E6%B4%8B%E4%B9%8B/dp/4798173266/ref=sr_1_15?crid=341O9294X80Z7&keywords=javascript&qid=1679238835&sprefix=javas%2Caps%2C185&sr=8-15)
で学習した内容を記載していく。[^1]
[^1]:本記事では変数、文字列、配列ついて記載した。

## 変数
#### letによる変数宣言
```
let 変数名 = 値;
```
letキーワードに続けて`変数名 = 値`と書くことで変数を宣言することができる。

## 文字列
#### 文字列の基本
```string_basic.js
const a = 'Hello would';
console.log(a);
```
「文字列」を記述するには、一連の文字をクォーテーションで囲む。文字列も数値と同じように、変数に格納することができ、`console.log()`でコンソールに直接表示させることができる。

## 配列
#### 配列の作り方
``` 
[要素1, 要素2, 要素3, ・・・]
```
要素をカンマ区切りで並べ全体をブラケットで囲む。
```create_array.js
const interests = ['読書', '料理', 'キャンプ'];
console.log(interests);
```

#### 配列の要素にアクセスする
```
配列[インデックス]
```
配列に続けて`[インデックス]`と書くことで、指定したインデックスにアクセスすることができる。
```array_element.js
const interests = ['読書', '料理', 'キャンプ',];
const element0 = interests[0]; // インデックス0の要素（先頭の要素）を取得
console.log(element0);
```

## 配列の操作
#### 要素の数を調べる
配列に続けて`.length`と書くことで、配列の要素数を得ることができる。
```array_length.js
const interests = ['読書', '料理', 'キャンプ'];
const count = interests.length; // 配列の要素数
console.log(count);
```

#### 要素を最後尾に追加する
配列に続けて`.push(追加したい要素)`と書くことで、元の配列の一番後ろに要素を追加することができる。
```
配列.push(追加したい要素)
```
```push.js
const interests = ['読書', '料理', 'キャンプ',];
interests.push('散歩'); // 配列の一番後ろの要素を追加
console.log(interests);
```

#### 最後尾から要素を取り出す
配列に続けて`.pop()`と書くことで、配列の最後の要素を取り出すことができる。
```
配列.pop()
```
```pop.js
const alphabet = ['a', 'b', 'c',];
const last = alphabet.pop(); // 配列の一番後ろに要素を取り出す
console.log(last);
```

#### 特定の要素が配列に含まれるか調べる
`includes()`を使うことで、特定の要素が配列に含まれるか調べることができる。
```
配列.includes(要素)
```
```includes.js
const fruits = ['みかん', 'りんご', 'バナナ',];
const check1 = fruits.includes('りんご'); 
console.log(check1);
```

#### 配列要素の結合と文字列の分割
`join()`は、配列の要素を結合して１つの文字列を返してくれる。
```
配列.join(区切り文字)
```
```join.js
const interests = ['読書', '料理', 'キャンプ',];
const a = interests.join('と'); 
console.log(a);
```
`join()`とは逆に「文字列」から「配列」を生成するには`split()`を使う。
```
文字列.split(区切り文字)
```
```split.js
const string = '読書&料理&キャンプ';
const a = string.split('&'); 
console.log(a);
```