OmniAICreator/Qiita-1.07M huggingface dataset:
Core i9 12900kのDebianマシンが起動しない（i915が原因だった）

Core i9 12900kのDebianマシンで計算させようと起動させました．しかし，アクセスできません．結論から言うとCPU内臓のGPUとDebianの相性が悪かったようです．

対処手順を書いておきました，Linuxで何か起きたときの対処法の参考になれば幸いです．

## 症状を見る
### ブート画面

ブート画面を見ると

```
/dev/sda2: clean, xxx/xxx files, xxx/xxx blocks
```
で止まっています．これでは何が起こっているか分かりません．SSDが壊れている可能性もありますが，可能性としては低いでしょう．詳細が知りたいのでrecovery modeで立ち上げます．

### Recovery modeでの起動

DebianでRecovery modeを立ち上げるには，GRUBでRecovery modeを選択する必要があります．DebianではGRUBが立ち上がると，
```
Debian GNU/Linux
Advanced options for Debian GNU/Linux
UEFI Firmware Settings
```
と表示されます．ここで
__Advanced options for Debian GNU/Linux__
を選択します．すると次のような選択肢がでます．
```
Debian GNU/Linux, with Linux xxx
Debian GNU/Linux, with Linux xxx (recovery mode)
```
ここでは，
__Debian GNU/Linux,with Linux xxx (recovery mode)__
を選びます．

### 止まる場所が判明

Recovery modeで起動すると処理の進み具合が分かります．するとi915に関する処理で止まることが判明しました．つまり，内蔵GPUのi915とDebianとの間に問題がありそうです．

## 解決法

### まずは起動
Debianが起動しないことには何も始まりませんので，まず起動させます．Grubが起動したらeを押して起動の一時的に設定を変えます．eを押すとDebianの起動の設定が出てきます．__i915が悪そうなので，i915のmodesetをオフにしてみます．__
__modesetをオフにするにはquietという単語のあとにi915.modeset=0を追加します．__
これで一時的にi915のmodesetが無効になります．modesetを無効にしたからといって起動するかどうか分かりませんが，modesetの無効化はGPU関係の問題を解決する定番の方法ですので試してみます．__modesetを無効化すると案の定起動しました．__

### 設定の恒久化

上記方法で起動はしましたが，これは一時的なものです．再起動すると上記で設定した内容は消え，再びboot途中で止まることになります．つまり，設定を恒久化しなければなりません．

 Grubの設定は/etc/default/grubに保存されています．次のコマンドで設定を編集します．
```bash
sudo nano /etc/default/grub
```
次に，modesetの無効化設定を追加します．無効化設定を追加するには
```
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
```
を
```
GRUB_CMDLINE_LINUX_DEFAULT="quiet i915.modeset=0"
```
に変更するだけです．

設定ファイルを書き換えましたが，まだ設定が反映されていません．次のコマンドで設定を反映させます．
```bash
update-grub
```
これで再起動してもi915のmodesetが無効化されたままです．

以上でDebianが起動しない問題が解決されました．
ITエンジニアの職務経歴書の書き方　３つのポイント

こんにちは。
ITエンジニアの中途採用を担当しています藤井です。

仕事上、毎日たくさんの職務経歴書を見ていますが、見やすい職務経歴書と、そうでない職務経歴書はやはり、差が出ますね。。。:sweat_smile:

今日はエンジニアの職務経歴書の書き方の３つのポイントをお伝えします！
このポイントを守るだけでも、かなり採用担当者から見てみやすい職務経歴書になるはず！
是非試してみてください！:smile:


■ポイント１：原則、箇条書きで書く

担当者は毎日、大量の職務経歴書をチェックしています。
たまに、文章で長く経歴書を書いている職務経歴書を見ますが、正直あまり良い印象は与えないでしょう。
相手がどのようなシチュエーションで、書類を見ているのか想像しながらビジネス文書を作成するのは基本ですよね。
要点が、短い時間で、相手に伝わるように、原則は箇条書きで簡潔に記載するのが、ポイントです。

それぞれの、経験してきた社歴ごとに、
主に経験してきた技術領域や、担当工程、開発言語やツールなどが簡潔にまとめられていれば良いでしょう。


■ポイント２：無理にすべてのプロジェクトを書こうとしない

経験してきたプロジェクトすべてを記載する必要も無いでしょう。
ITエンジニアの方の中には、数カ月のプロジェクトをたくさん経験してきた、なんて方もいるはず。
そのすべてを記載すると、かなり分かり辛い経歴書になってしまいます。
ここも会社歴ごとに概要をまとめて記載すれば充分です。


■ポイント３：A4、3ページ以内で作成する

適切な分量はA4で最大でも3ページ。
若手エンジニアの方は1～2ページでも充分です。
経歴書ですべてを伝えようとするのでは無く、最低限必要な情報をシンプルにまとめて、必要な事は面接でしっかりアピールしましょう！


いかかでしたか？重要なポイントは簡潔に分かりやすく！
これは、職務経歴書に限らず（ドキュメントに限らず）全てビジネスコミュニケーションの基本になります。
書類の書き方ひとつで、要点を捉えたコミュニケーションが取れるITエンジニアなのかも、採用担当は見ています。

気合を入れて、超大作な職務経歴書を時間をかけて作成しても、あまり評価されないと悲しいですよね。。。:sob:

シンプルで、スマートな職務経歴書で、転職活動も頑張ってください！
それでは、今日も良い一日を！
LaravelのupdateOrCreateで重複エラーになる場合の対応

## 現象

- 多重リクエストされると、updateOrCreateが効かずにinsertが多重実行されることがある

## 対策

- 例外をcatchして無視する

### 実装例

```php
try {
    DB:::transaction(function() use ($answers) {
        foreach ($answers as $num => $answer) {
            Survey::updateOrCreate([
                'survey_num' => mb_sbstr($num, -1),
                'answer' => $answer,
            ]);
        }
    });
} catch (\Illuminate\Database\QueryException $ex) {
    if ($ex->errorInfo[1] !== MySQLErrorCode::DUPLICATE_KEY_ENTRY) {
        throw $ex;
    }
    // 多重リクエストされるとupdateOrCreateが効かずにinsertが多重実行されるため無視する
    Log::info('回答が重複して挿入されたため無視しました');
}
```
Amazonの商品ページのURLを短くしてコピーしたいときに使うブックマークレット

**なぜ /dp/XXXXXXX の前に文字列があるんだ、、、**

## このブックマークレットについて

Amazonを回遊しているときにリンクを残しておきたいけど余計な文字列を削りたくなること、ありますよね！（7/12現在、いまちょうどAmazonプライムデー実施中なので）

そんな時にコピーしてシェアしやすいAmazonのURLを生成するブックマークレットを作りました！

事前に後述のブックマークレットをブラウザのブックマークに登録しておき、Amazonの商品ページを開いた状態で実行すると、

```
https://www.amazon.co.jp/JavaScript-%E7%AC%AC7%E7%89%88-David-Flanagan/dp/4873119707/ref=sr_1_1?
keywords=javascript+%E3%82%AA%E3%83%A9%E3%82%A4%E3%83%AA%E3%83%BC&qid=1689093702&sprefix=javascript+o%2Caps%2C219&sr=8-1
```

のようなURLから、

```
https://www.amazon.co.jp/dp/4873119707/
```

のように短いAmazon商品ページのURLをプロンプトで表示してくれます。

ちなみにAmazon.co.jpの商品ページ以外のページの場合は、URLは変換されずにそのまま出力されます。

## ブックマークレット本体コード

以下のコードをブックマークレットとして登録します。

```js
javascript:function amazonLinkShorter(url){const match = url.match(/https:\/\/www\.amazon\.co\.jp\/(.*\/dp|dp)\/(.*)\//);if (match){return `https://www.amazon.co.jp/dp/${match[2]}/`;}return url;};prompt('Amazon URL', amazonLinkShorter(location.href))();
```

:::note warn
(7/20追記) [コメント欄](#comments)も必見です！改良版を教えていただきました。ありがとうございます！
皆さんいろいろ工夫されていていて勉強になります！
:::

## ブックマークレットの追加方法と使い方

Google Chromeの場合は、以下の手順でブックマークレットを追加できます。

### 事前作業

1. ブックマーク欄の空いているところを右クリック→ `ページを追加...`
2. 「名前」欄にお好きなブックマークレット名を入力
    * 例: `[Amazon Link]`
3. 「URL」欄に前述のブックマークレット本体コードをコピペ
4. ブックマークレット保存先を選んで「保存」

### ブックマークレットを使う

1. お好きなAmazonページを開く
   * 例: [JavaScript 第7版 | David Flanagan, 村上 列 |本 | 通販 | Amazon](https://www.amazon.co.jp/JavaScript-%E7%AC%AC7%E7%89%88-David-Flanagan/dp/4873119707/ref=sr_1_1?keywords=javascript+%E3%82%AA%E3%83%A9%E3%82%A4%E3%83%AA%E3%83%BC&qid=1689093702&sprefix=javascript+o%2Caps%2C219&sr=8-1)
2. ブックマークレットを実行する
3. プロンプトが表示されるのでURLをコピーする

## 補足

ブラウザの種類やバージョンによって手順は変わってきますので、適宜調整してください。

それではまた。
Pythonで「ピボットテーブルみたいなの書きたい」と思ったので、ChatGPTに聞いてみたら

# やりたいこと

PandasのDataframeでdf1を変形して、df_newのようなデータ構造にしたいんです。

```Python
df1 = pd.DataFrame(
    data={'区分': ['なし', 'S部', 'S部', 'S部', 'S部', 'G部', 'G部', 'G部', 'G部', 'その他', 'その他', 'その他'], 
          'State': ['初級', 'なし', '初級', '中級', '上級', 'なし', '初級', '上級', '事務局', 'なし', '初級', '中級'],
          'Size': [1, 12, 8, 125, 7, 5, 2, 4, 3, 26, 5, 9]}
)

df_new= pd.DataFrame(
    data=np.array([[  0,  1,   0,  0, 0],
                   [ 12,  8, 125,  7, 0],
                   [  5,  2,   0,  4, 3],
                   [ 26,  5,   9,  0, 0]]),
    index=['なし', 'S部', 'G部', 'その他'],
    columns=['なし', '初級', '中級', '上級', '事務局']
             )
```

# ソリューション

例によって、ChatGPTに聞いたら、なんのことはない、「ピボットテーブル使え」と言われました。
相変わらず、秒で答えをくれるChatGPTさん。

```Python:Sample.py
import pandas as pd
import numpy as np

df1 = pd.DataFrame(
    data={'区分': ['なし', 'S部', 'S部', 'S部', 'S部', 'G部', 'G部', 'G部', 'G部', 'その他', 'その他', 'その他'], 
          'State': ['初級', 'なし', '初級', '中級', '上級', 'なし', '初級', '上級', '事務局', 'なし', '初級', '中級'],
          'Size': [1, 12, 8, 125, 7, 5, 2, 4, 3, 26, 5, 9]}
)

df_new = df1.pivot_table(index='区分', columns='State', values='Size', aggfunc='sum', fill_value=0)

print(df_new)
```

めっちゃ簡単やん…と思いました。

（おわり）
【Flutter】アクセストークンの秘匿化


# 注意

:::note warn
セキュリティリスク等の観点で、私の知識不足がございました。
そのため、新たにENViedパッケージを使用してAPIキーを読み込む記事を書きました。
:::
https://qiita.com/myzw1mt3/items/1543c3e1307fb89279fa


## やりたいこと
APIを使用する時にアクセストークンを用いることがあるかと思いますが、ソースコードにベタがきしてしまうと、GitHub等に公開した際に丸見えです。
そのためアクセストークンは秘匿化しておきたい。

## 1.パッケージインストール
[flutter_dotenv](https://pub.dev/packages/flutter_dotenv)というパッケージを使用します。
.envファイルから環境変数を読み込むための便利なパッケージです。

:::note info
環境変数は、アプリケーションの設定や認証情報などの機密情報を外部のファイルに保存し、アプリの実行時に読み込むために使用されます。
:::
ターミナルで以下を叩く。
```zsh
flutter pub add flutter_dotenv
```

## 2.envファイルの作成
### ①.envファイルを作成。
ルートディレクトリの直下に`.envファイル`を作成します。

:::note info

.envファイルは、アプリケーションで使用される環境変数を定義するためのテキストファイルです。
:::

### ②アクセストークンを記述
作成した.envファイルに以下のように記載します。
```env
ACCESS_TOKEN=******************************
```
*****に作成したアクセストークンを記述します。

## 3.`.gitignore`に.envを追加
上記で入力したアクセストークンが公開されないように`.gitignore`に.envファイルを追加します。
```gitignore
# .env ファイルを追加
.env
```

## 4.`.envファイル`をassetに追加
```yaml:pubspec.yaml
  assets:
    - .env
```

## 5.`.envファイル`を読み込む
`main.dart`で.envファイルを読み込みます。
```dart:main.dart
import 'package:flutter_dotenv/flutter_dotenv.dart';

Future<void> main() async {
  await dotenv.load(fileName: '.env');
  runApp(const MyApp());
}
```
`dotenv.load`関数は、指定されたファイル名（ここでは.env）のファイルから環境変数を読み込みます。

これで以下のようにdotenv.env['ACCESS_TOKEN']でアクセストークンを呼び出すことが出来ます。

```dart
final String token = dotenv.env['ACCESS_TOKEN'];
```
【忘備録】Pythonでシリアル通信受信してみた


M5STACKで出力したデータをシリアル通信で受信してみました。


*事前準備*：
・M5STACKにHS-SR04の超音波センサをつないで距離の値を出力

```python:
import serial
import time

# setting
COM     = "COM3"
bitRate = 9600

# open serial connection
ser = serial.Serial(COM, bitRate, timeout=0.1)

# receive serial
while True:
    time.sleep(0.1)

    ## reakd serial
    result = ser.read_all()
    print(result)

print("program end")

# closer serial
ser.close()

```

*参考*
https://engineer-lifestyle-blog.com/code/python/pyserial-communication-usage/
Salesforce承認プロセスについて分かりやすく解説してみた

こんにちは
本橋孝昭です

今回はSalesforce承認プロセスについて分かりやすく解説しました

今回の内容は動画でも解説しています

https://youtu.be/VQzZNz_HGHQ

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

# そもそも承認プロセスってなんだ？

承認プロセスとはSalesforceから特定のレコード情報を承認申請してマネージャーや上長から承認してもらうための機能です

一般的な会社では
・○○億円以上の案件の場合、営業は案件内容を一度上長に確認してもらい、
問題なければ承認される
・名刺作成依頼など○○依頼を総務部にして、総務部から承認を得る
・○○をする際は、部長と社長の承認が必要

のような承認される動きがあると思います
このような承認の際に、今までは稟議書などの書類を回して社内でハンコリレーをしていたのかもしれないです。
![稟議.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ee967225-7999-aca9-fb14-e168eb41c5b8.png)

これが承認プロセスでは

1.稟議書の紙の書類が不要になる→Salesforce上で完結
2.承認の申請の通知が自動で可能→Salesforce上でメールでの通知など設定をすれば申請時に承認者に即連絡が届く
3.承認のハンコが不要になる→Salesforce上で承認、却下の履歴が残る
4.承認、却下の通知が自動で可能→Salesforce上でメールでの通知など設定をすれば承認や却下時に申請者に即連絡が届く


となります
この承認プロセスを使いこなせば、なんだか一気に社内のIT化が加速しそうですね

ぜひこの承認プロセスの設定について見ていきましょう

# 承認プロセスの設定方法

承認プロセスの設定方法は大きく　６つです

![承認プロセス１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/58d10043-8194-b7d0-7488-a2987b210890.png)

## 1 開始条件
どの条件でこの承認プロセスを起動するか　です

## 2 申請時のアクション
申請時にどのような設定をするか　です
・レコードをロックして申請内容を編集不可にする
・メール通知をして承認者にメールを飛ばす
などはここから設定可能です

## 3 承認ステップ
ここで承認者が何人必要か　を設定します
もしも承認者が
・田中太郎
・鈴木次郎
と二段階が前であれば
・田中太郎の承認ステップ
・鈴木次郎の承認ステップ
と２つの承認ステップが必要です

## 4   最終承認時のアクション
最終承認時のアクションの設定を行います
・レコードをロック解除して申請内容を編集可能にする
・メール通知をして申請者にメールを飛ばす
などはここから設定可能です

## 5   最終却下時のアクション
最終却下時のアクションの設定を行います
・メール通知をして申請者にメールを飛ばす
などはここから設定可能です

## 6   取り消し時のアクション
取り消し時のアクションの設定を行います
・メール通知をして申請者にメールを飛ばす
などはここから設定可能です

## よくある質問～ユーザによって承認者を変えたい

よくある質問として
・ユーザによって承認者を変えたい
があります
例えば小さい会社ですと
・（誰が申請しても）承認者は絶対に鈴木次郎社長
と簡単ですが、組織は複雑だと

・田中太郎さんが申請するときは田中さんの上長の佐藤さんが承認者
・山田一郎さんが申請するときは山田さんの上長の山本さんが承認者

というユーザごとに承認者を変えたい場合がありますね

その場合はユーザの項目からマネージャーを設定して承認ステップを「上長」に設定しましょう

![承認者002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1208ef05-14b4-d0ad-1561-b9a0ab598c24.png)

そして
割り当て先として使用するユーザ項目　えお
レコード所有者のマネージャ
に設定しましょう

![割当先.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e83f17ab-aed3-d5b0-93f7-6b61829cf797.png)


## よくある質問～ユーザによっては代理承認者を立てたい

こちらもユーザ項目から代理承認者の設定を行いましょう

![承認者002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1208ef05-14b4-d0ad-1561-b9a0ab598c24.png)

## よくある質問～承認時、却下時、取り消し時などでどのような設定が可能か？

・Todo
・メールアラート
・項目自動更新
・アウトバウンドメッセージ
の４つが設定可能です

![todo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/6be65e95-8e95-3537-281e-e64624d6856a.png)




こちらで承認プロセスの説明は終わりです

最後に承認プロセスの「弱点」をご紹介します


# 承認プロセスの弱点～基本的に手動で「承認申請ボタン」を押さないと承認されない～

最も困った設定としては、承認プロセスそのものは自動で動くことはないです
そのため、ユーザが手動で「承認申請ボタン」を押さないと承認プロセスは動きません

しかしながら、
・○○億円以上の案件の場合、営業は案件内容を一度上長に確認してもらい、
問題なければ承認される
のような業務の流れがある場合は自動で承認プロセスが起動されたいですよね

その場合、自動起動されるフローなどを作成し、特定の条件になった場合に起動させます

フロー作成の方法については別途まとめたのでこちらご確認ください

※Salesforceでフローを作成しよう～特定の値のレコードを自動で承認プロセスを起動させる方法
https://qiita.com/Takaa/items/cf6b7a4079b4dd6e31ee
PHP、CURLFileでファイルをアップロードする。(multipart/form-data、POST)

PHP、CURLFileでファイルをアップロードするコードです。
試行錯誤したので備忘録として残します。
※$_FILES、"Content-Type: multipart/form-data"、POSTを使用しています。

# 本記事の環境

ホストOS：Windows10 Pro 64bit 8GB
ゲストOS：Red Hat Enterprise Linux release 8.3 (Ootpa)
Oracle VM VirtualBox：6.0.4a
vagrant：Vagrant 2.2.14
Apache：2.4.37
PHP：PHP 7.4.15
Tera Term：4.105
コマンドプロンプト
ホストOS側に実ソース

# ソースコード

```php
$curl_file = new \CURLFile($_FILES['uploadfile']["tmp_name"], $_FILES['uploadfile']["type"], $_FILES['uploadfile']["name"]);
$option = [
    'aaa' => 'AAA',
    'bbb' => 'BBB',
];
$option_encode = json_encode($option);
$param = [
    // $curl_fileと、その他に必要なパラメータがあればここに追加。
    'file' => $curl_file,
    'pass' => "abcdef",
    'option' => $option_encode,
];
$postdata = $param;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://xxx.jp/yyy/zzz.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data"));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
$result = curl_exec($ch);
$result_decode = json_decode($result, true);
```
GolangとCloud SpannerでgRPC APIを構築する #1

この抜粋の内容は次のとおりです。

- Cloud Spanner Emulator の導入
- Spanner で CRUD
- gRPC API の実装: [connect-go](https://github.com/bufbuild/connect-go)

```mermaid
flowchart LR
    docker["docker
    emulator"]
    devcontainer["devcontainer
    Go"]
    devcontainer -->|host.docker.internal:9020| docker
```

さらに詳しく知りたい方は読み続けてください。

---

2023年7月2回目です。

普段、ぼくたちの Database の第一の選択肢は、Cloud SQL です。

ですが、今後、可用性が求められるフェーズに対応するために、[Cloud Spanner](https://cloud.google.com/spanner?hl=ja) での開発について調査します。

- Cloud Spanner は、今のサービス群で使うには高価です。最小サイズが Processing Unit になったとは言え。
- 一方で、強整合性を持ちながらグローバルな負荷分散が可能で、これを CockroachDB などで運用すると考えると妥当な価格であることも認識しています。

## Cloud Spanner Emulator の導入
- gRPC リクエストの場合は localhost:9010 、REST リクエストの場合は localhost:9020 です。[公式](https://cloud.google.com/spanner/docs/emulator?hl=ja#install-gcloud) を参照。
```bash
docker pull gcr.io/cloud-spanner-emulator/emulator
docker run -p 9010:9010 -p 9020:9020 gcr.io/cloud-spanner-emulator/emulator
```
- 疎通を確認する
```bash
curl http://host.docker.internal:9020
```
- Emulator 用の環境変数を定義する
```bash
export SPANNER_EMULATOR_HOST=host.docker.internal:9010
echo $SPANNER_EMULATOR_HOST
```

## Spanner で CRUD
- 接続に `SPANNER_EMULATOR_HOST` を使います。
### Instance の準備

https://github.com/danny-yamamoto/go-spanner-example/blob/main/cmd/create_instance/main.go

### Database の準備

https://github.com/danny-yamamoto/go-spanner-example/blob/main/cmd/create_database/main.go

### Data の準備
- schema を実行する方法もあります。

https://github.com/danny-yamamoto/go-spanner-example/blob/main/cmd/insert_data/main.go

## gRPC API の実装
- 今回は、connect-go で実装します。

https://github.com/danny-yamamoto/go-spanner-example/blob/main/cmd/server/main.go

## Summary
* Cloud Spanner での開発について調べました。
* 気になることがまだたくさんあります。これらは、継続して実装します。
    - Database 接続まわりは、どうするのが一番良いのか？
    - Transaction 処理の実装の方法は？

今回の[コード](https://github.com/danny-yamamoto/go-spanner-example)です。

https://github.com/danny-yamamoto/go-spanner-example
[Laravel 10.15] 生SQLを実行する必要がある方注目！toRawSql()でEloquentからバインド値が組み込まれたSQL文を出力できるようになった！

## はじめに

Laravelが提供しているEloquentというORMは非常に便利で、複雑なクエリも簡単に作成できます。便利なのですが、残念ながらEloquentが使えない場合もあります。

たとえば、クエリのコストや負荷を計測するための`explain`を実行したい場合です。
もう一つは、弊社では安全のために`本番のtinkerでコマンドを実行しないルール`があり、データ抽出の依頼があった場合にはDBのレプリカで生のSQLを実行することになっています。

そのような場合、Eloquentから生のSQLに変換するために`dd()`や`toSql()`といった関数もありましたが、出力されるSQLにクエリパラメータがバインドされず、`?`というプレースホルダのままになってしまいました。そのため、手動でクエリパラメータをSQL文に置き換える必要がありました。

Laravel 10.15のリリースでは、`toRawSql()`関数が追加され、バインドされた値が含まれたSQL文を出力できるようになりました。

## toSql()・dd()・toRawSql()比較

### 今まであったdd()・toSql()

実行したいselectクエリーの最後に`get()`の代わりに`dd()`もしくは`toSql()`を使用すると、SQL文を出力することができます。

`dd()`の機能はSQL文だけでなく、クエリパラメーターの配列も一緒に出力されます。

```php
User::where('created_at', '>', '2023-01-01 00:00:00')->dd();

// "SELECT * FROM users WHERE created_at > ?"  
// array [ 
//  "2023-01-01 00:00:00"
// ]
```

`toSql()`の場合、SQL文のみが出力されます。クエリパラメータを出力したい場合には、以下のようにクエリビルダーを変数に代入してから`getBindings()`を実行すると、パラメータの配列が出力されます！

```php
$query = User::where('created_at', '>', '2023-01-01 00:00:00'); // クエリビルダを代入

$query->toSql(); // toSql()を実行しSQL分を出力

// "SELECT * FROM users WHERE created_at > ?" 

$query->getBindings(); // パラメーターの配列を出力

// [
//    "2023-01-01 00:00:00",
// ]
```

確かに、両方は非常に便利な機能ですが、生のSQLを実行する前に、SQL文内の`?`を手動でコピーペーストで置き換える必要があるため、時間がかかる上にミスの可能性もあります。

### 新しく追加されたtoRawSql()

`dd()`や`toSql()`と同じような使い方でバインド値が組み込まれたSQL文が出力できます。

```php
User::where('created_at', '>', '2023-01-01 00:00:00')->toRawSql();

// "SELECT * FROM users WHERE created_at > '2023-01-01 00:00:00'"
```

ご覧のように、出力されたクエリをそのままコピーペーストし、直ぐにSQLのサーバー（弊社の場合、本番のレプリカ）ですぐに実行することができます！非常に便利な機能ですね！

## まとめ

`toRawSql()`の機能により、Eloquentのクエリをパラメータが含まれたSQL文として出力することができるようになりました。これにより、コピーペーストの手間やミスが減り、非常に便利な機能となっています。

SQLに苦手意識のある方や、Eloquentが実行したクエリの内容やコストを確認したい方はぜひお試しください！


## 参考

[関連のPR](https://github.com/laravel/framework/pull/47507)
[Laravel10.15のリリース](https://github.com/laravel/framework/releases/tag/v10.15.0)
いまさらながらGo言語に触れる

## はじめに
タイトル通り、いまさらながらGo言語について学習し始めたので、記事として残します。

### Go言語とは

GoはGoogleが開発した静的型付けのコンパイル言語で、シンプルさと効率性を重視して設計されています。Goは非常に高速で、並行プログラミングをサポートしています。これは、CPUコアを効果的に利用して、高性能なアプリケーションを作成するために重要な特性です。

### プログラムの構造

Goのプログラムはパッケージとして組織されています。`main`パッケージは特別で、Goプログラムの実行は`main`パッケージから始まり、`main`関数から始まります。例えば：

```go
package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}
```

このプログラムは"Hello, world!"と出力します。`fmt`は標準ライブラリの一部で、フォーマットされたI/Oを提供します。

### 変数と定数

Goでは、`var`キーワードを使って変数を宣言します。例えば：

```go
var x int
x = 10
```

または、初期化と一緒に変数を宣言することもできます：

```go
var x int = 10
```

また、`:=`演算子を使用して、型宣言を省略することもできます。この場合、変数の型は右辺の式から推論されます。

```go
x := 10 // x is an int
```

定数は`const`キーワードを使って宣言します。定数は、コンパイル時に値が決定され、その後は変更できません。

```go
const Pi = 3.14
```

### データ型

Goには、以下のような基本的なデータ型があります：

- **整数型（int、uint、int8、uint8、int16、uint16、int32、uint32、int64、uint64）**: `int`と`uint`は、32ビットシステムでは32ビット、64ビットシステムでは64ビットです。`int8`、`int16`などの型は、数値の範囲を示しています。たとえば、`int8`は-128から127までの値を持つことができます。

- **浮動小数点型（float32、float64）**: これらは小数点以下の数値を持つことができます。

- **複素数型（complex64、complex128）**: これらは複素数を表します。

- **ブール型（bool）**: `true`または`false`の値を持つことができます。

- **文字列型（string）**: テキストを表します。

### 制御フロー

Goには、他の多くのプログラミング言語と同様に、`if`、`for`、`switch`といった制御フロー構造があります。

- `if`は条件分岐を行います：

  ```go
  if x > 0 {
      fmt.Println("x is positive")
  }
  ```

- `for`はループを行います。Goには`for`文しかループ構造がないため、他の言語の`while`ループや`do-while`ループを模倣することもできます：

  ```go
  for i := 0; i < 10; i++ {
      fmt.Println(i)
  }
  ```

- `switch`は多方向の分岐を行います：

  ```go
  switch x {
  case 0:
      fmt.Println("x is zero")
  case 1:
      fmt.Println("x is one")
  default:
      fmt.Println("x is neither zero nor one")
  }
  ```

もちろんです。それでは、Goにおける関数とエラー処理について学んでいきましょう。

### 関数の定義と呼び出し

Go言語では、`func`キーワードを使って関数を定義します。以下に関数の基本的な定義を示します。

```go
func greet(name string) {
    fmt.Println("Hello", name)
}
```

この例では、`greet`という名前の関数を定義しています。この関数は一つのパラメータ`name`を受け取り、"Hello"とそのパラメータを出力します。

この関数を呼び出すには、以下のようにします。

```go
greet("Alice")
```

このコードは"Hello Alice"と出力します。

### 複数の戻り値

Go言語では、一つの関数が複数の値を返すことができます。これは、エラーハンドリングや複数の結果を返す必要がある関数を書く際に非常に便利です。

```go
func divmod(a, b int) (int, int) {
    return a / b, a % b
}
```

この例では、`divmod`関数は商と余りを返します。この関数を呼び出すには、以下のようにします。

```go
quotient, remainder := divmod(7, 3)
fmt.Println("quotient:", quotient)
fmt.Println("remainder:", remainder)
```

このコードは以下のように出力します。

```
quotient: 2
remainder: 1
```

### エラーハンドリング

Go言語では、エラーハンドリングは`error`型を用いて行います。エラーが発生する可能性がある関数は、通常、戻り値として最後に`error`型の値を返します。

以下に、エラーハンドリングの例を示します。

```go
func sqrt(x float64) (float64, error) {
    if x < 0 {
        return 0, errors.New("undefined for negative numbers")
    }
    // Compute and return square root of x
}
```

この例では、`sqrt`関数は負の数に対しては定義されていないため、`x`が負の場合にはエラーを返します。この関数を呼び出す際には、エラーをチェックする必要があります。

```go
result, err := sqrt(-1)
if err != nil {
    fmt.Println("Error:", err)
} else {
    fmt.Println("Result:", result)
}
```

このコードは"Error: undefined for negative numbers"と出力します。
【小ネタ】Gitで草を生やす際に日程がずれていた時の対処法

ほんとに小ネタです。
ちなみに草を生やすとはGit上で何か活動した際に日にちのマス目が緑色に塗りつぶされ、活動記録が残るところからきています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/4c4067b0-5649-7fb0-fb51-64d7e408427a.png)


## 事象
日本時間の2023/7/12/朝8:15頃、少々コードを編集してリポジトリにpushしたところ、一日前の7/11に草が生えていた。

## 原因
案の定タイムゾーンが原因でした。ギリギリ7/11になっています。
```bash
$ date
Tue Jul 11 23:17:18 UTC 2023

$ timedatectl
               Local time: Tue 2023-07-11 23:17:54 UTC
           Universal time: Tue 2023-07-11 23:17:54 UTC
                 RTC time: Tue 2023-07-11 23:17:54
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
```

## 解決策
タイムゾーンを東京に変更するだけで解決です。
```
$ sudo timedatectl set-timezone Asia/Tokyo
$ date
Wed Jul 12 08:18:13 JST 2023
```

## 結果
再び適当にコードを編集してpushしたところ、無事に元の日時(7/12)に草が生えました。
前日(7/11)ほんとは何もしていないのですが、タイムゾーンをいじる前の草は生えたままですね…。（写真赤枠のすぐ上）時間が経ったら自動修正されるかもしれませんが、ほんの少し得した？気分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/030a0dcc-86c8-c893-059d-e757f63c147b.png)
【パッケージマネージャ】npmとyarnについて

## はじめに
皆さん馴染みの深い`npm`と`yarn`について、違いを意識して使い分けしていますか?

両者とも**Node.js**で動作する**パッケージマネージャ**という理解はありましたが、双方の違いについて
あまり意識してませんでした。

ふと気になったので、今回は`npm`と`yarn`の概要と違いについてまとめていこうと思います

## パッケージマネージャーとは
パッケージマネージャとはその名の通り、パッケージを管理するソフトウェアやシステムのことを指します。
主にシステムのインストールやアンインストール、必要な外部のソフトウェアの自動取得（依存関係の解決）などを行ないます。

大まかに2種類に分けられ`OSレベルの機能やソフトウェアパッケージを管理するもの`と`プログラミング言語`向けもの`があります。

## npmとは　
npmとは`Node Package Manager`の略称で2010年1月にリリースされたJavaScript公式の
パッケージマネージャーのことです。

## yarnとは
yarnとは`Yet Another Resource Negotiator`の略称で、2016年10月にFacebookによってリリースされた「npm」の代替手段です。

当時のnpmはインストールは時間がかかりセキュリティに関してもパフォーマンスに関して
問題が山積みでした。

それらを解決したのが、当時の`yarn`になります。

セキュリティにおいての改善点ですが、インストール時にパッケージが不正に変更されていないかなどをチェックサムを用いて検証することができ、安全なパッケージのインストールを可能にしました。

また、パッケージ管理においては`yarn.lock`というファイルが作成され、それにはインストールしたプログラムが使用している依存プログラム/パッケージのバージョンが明確に書き込まれます。
これにより、依存プログラム/パッケージを再インストールした際も整合性が保たれるので、デプロイ時にバージョンが違って動かなるといったことは無くなりました。

## 結論どっちが良いの?
**現在はどちらでも良いと言うのが結論です。**

昔はnpmのインストールが遅い、yarn独自の機能がある等ありましたが現在では
`lock`ファイル等のyarnの機能もnpmに搭載されてパフォーマンスにほぼ差異はなくなっております。

ただ、個人的にはパッケージをインストールする際に`yarn`と打っただけでインストールできるので`yarn`の方が好みです。

因みに速度については **npm v7 (2020-10-13)** でかなり改善されて同等のものになりました。
リリースノート等あるので、気になる方は下記を見てください！

https://github.com/npm/cli/releases/tag/v7.0.0

https://github.blog/2020-10-13-presenting-v7-0-0-of-the-npm-cli/

https://blog.npmjs.org/post/621733939456933888/npm-v7-series-why-keep-package-lockjson







## 参考記事
[パッケージマネージャーとは？わかりやすい仕組みの解説～直接使っていないOSSとは～](https://www.hitachi-solutions.co.jp/sbom/sp/blog/2023033101/)
[パッケージ管理システム](https://e-words.jp/w/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0.html)
[node_modulesの問題点とその歴史 npm, yarnとpnpm](https://zenn.dev/saggggo/articles/dbd739508ac212)
[npmとは　yarnとは](https://qiita.com/Hai-dozo/items/90b852ac29b79a7ea02b)
[【JS】yarnの長所とyarnからnpmに戻ってきた理由](https://jsnotice.com/posts/2020-09-02/index.html)
TF-C 時系列データの対照学習

時系列データに対して広く一般化可能な事前学習をする戦略です。


こちらを見て関心を持ちました。

https://ai-scholar.tech/articles/time-series/TFC-pretraining

画像の自己教師あり学習については、以前こんなのを書いています。

https://qiita.com/h1day/items/c1de82e011b507b03d35

### 基本情報

| 項目 | 内容 |
| -- | -- |
| タイトル | Self-Supervised Contrastive Pre-Training For Time Series via Time-Frequency Consistency |
| 著者| Xiang Zhang, Ziyuan Zhao, Theodoros Tsiligkaridis, Marinka Zitnik (Harvard University, MIT Lincoln Laboratory)|
| NeurIPS  | https://openreview.net/forum?id=OJ4mMfGKLN |
| ariXiv | https://arxiv.org/abs/2206.08496|
| ariXiv-vanity | https://www.arxiv-vanity.com/papers/2206.08496/|
| github | https://github.com/mims-harvard/TFC-pretraining |
| project | https://zitniklab.hms.harvard.edu/projects/TF-C/|

# どんなもの?

自己教師あり対称学習を使って、時系列データに対して広く一般化可能な事前学習をする戦略です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/31cea4e9-423a-351d-f2d0-ed1748dc47dc.png)


### 動機

- 時系列の広く一般化可能な表現を学習することは根本的に困難な問題
    - ドメインの異なるデータセットへの転移学習が難しい
        - データセット間の時間ダイナミクスの大きな変動、
        - 信号の意味の違い
        - システム要因
    - 大規模な教師付きデータが必要
        - 医療分野なら専門家の判定が必要 

- 一方で他分野は
    - CV: 初期神経層がエッジや形状など画像スタイルやタスクに関係なく普遍的な視覚要素を捉えるという知見
    - NLP：文法、意味論 といった共通部分

### アプローチ

信号理論によれば、時系列データは時間領域でも周波数領域でも等価に表現できる。
この不変な性質を使って効果的な事前学習を行う。

# 先行研究と比べてどこがすごい?

- 完全にラベル付けされていない事前学習データセットで使用することができる。

- 異なる種類のセンサーや計測値を持つ時系列データセットを含む4つのシナリオにおいて、効果的な転移を提供。
    - ドメインギャップが大きい場合（例えば、事前学習と微調整のデータポイントが異なる特徴空間で与えられたり、異なる意味的意味を持つ場合）でも、強力な性能を達成することが示された。

# 技術や手法のキモはどこ?

これらの重み付きの和がLOSS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/dffe4fb9-cb08-7fe7-9a1f-16384b37b01e.png)


- 時間表域での対照学習
    - jittering, scaling, time-shifts, and neighborhood segments で変化させても特徴量空間で同じ表現になるようにする。 
    - 以下の式で、同じデータならコサイン類似度が１、異なるデータなら-1になることを目指す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/dd8e16d7-3427-d774-8f07-8627da7d1244.png)

- 周波数領域での対照学習
    - ランダムに周波数成分の追加と削除をする。
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/51daadfd-7290-1735-3609-aa0621d4ec84.png)

    - 式の形は時間領域と同じ。
- 時間領域での表現と周波数での表現の一貫性
    - 摂動あり/なしの組み合わせに対して実施
    - Sは時間領域と周波数領域のデータの組み合わせでコサイン類似度が１、異なるデータなら-1になることを目指す式。摂動なしの同じデータのTとFの表現が、摂動蟻を含む場合に比べてより一致することを目指している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/35534f19-4472-b365-6edd-27a5482735a8.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/3aaaed40-0549-211c-c347-ad960d3e9ea6.png)


# どうやって有効だと検証した?

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/f2f7b4ae-e5aa-4dc0-75d9-e645349fa88a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/5e8db8b1-677c-7c7f-a5a2-8c0366753bdd.png)


# 議論はある?

Appendix K によると事前学習に複数のデータセットを組み合わせることはうまくいっていない模様。


# 次読むべき論文は?

？
名刺を電子ペーパーにしました

こちらの記事が面白かったので、私も最近、名刺を電子ペーパーにした話を紹介します。

https://qiita.com/mitsuharu_e/items/2684ade79d7a8d37b2f7

# 入稿データがない！

名刺のストックが減ってきたのですが、以前の発注がコロナ禍前で入稿データが見当たらなくなってしまいました。

気楽な零細企業なので、これを機に名刺を電子ペーパーにしてみました。

![IMG_0610.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35178/c9369fa9-db80-8b12-ccc6-b3abcd8aef7e.jpeg)

下の方にNFCタグがついていて、スマホでタッチするとプロフィールページが表示されます。

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

# 使った製品

電子ペーパーはこちら。

https://www.amazon.co.jp/dp/B08KYGSXV4/

NFCタグはこんな感じのコイン型です。

https://www.amazon.co.jp/dp/B0B12NH3PQ/

# 名刺の書き込み

こちらの電子ペーパーはスマホアプリで簡単に書き込み・書き換えができます。

https://apps.apple.com/jp/app/nfc-e-tag/id1518982217

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

電子ペーパーなので電池がいりません。書き込み時もNFCで電源不要というのが便利！

# タッチしたときのリンク先の書き換え

こちらのアプリを使いました。

https://apps.apple.com/jp/app/nfc-tools/id1252962749

本当は紙の名刺を渡すのが、相手も慣れているのでよいと思いますが、新しいこと(変なこと)を試してみようと思います。
Strapi v4でカスタムプラグインを作ろう！

## 概要
Strapi(v4)でカスタムプラグインを作成する方法を紹介します。

言語はTypeScriptを使用しています。


 ## プラグインの作成
以下のコマンドを実行

npm
`npm run strapi generate plugin`

yarn
`yarn strapi generate plugin`


プラグインの名前はどうする？と聞かれるので、任意のプラグイン名を入力します。
（今回は`sample-plugin`という名前で作成）
```
$ strapi generate plugin
? Plugin name sample-plugin
```

## Pluginのディレクトリ構成
プラグインを作成すると`src/plugins`配下にプラグインのフォルダが作成されます。

``` 
├──admin
│   └── src
│       ├── components
│       ├── index.tsx
│       ├── pages
│       ├── pluginId.ts
│       ├── translations
│       └── utils
├── custom.d.ts
├── dist
├── node_modules
├── package.json
├── server
├── strapi-admin.js
├── strapi-server.js
├── tsconfig.json
├── tsconfig.server.json
├── yarn-error.log
└── yarn.lock
```

`admin/src`配下ではプラグインのページを構成するファイルが置かれており、Reactで書かれている。

## Configファイルの設定

管理画面で作成したプラグインを使用できるようにするためには設定ファイルを追記する必要があります。

プロジェクトのルートディレクトリにあるconifgフォルダに`plugins.ts`を作成し、以下の内容を記述
```ts
export default {
  'sample-plugin': {
    enabled: true,
    resolve: './src/plugins/sample-plugin'
  },
}

```


## 管理画面で確認する

プラグインを管理画面で表示させるためにはプラグイン構成ファイルをビルドする必要があります。

```bash
# プラグインの構成フォルダ配下に移動
cd src/plugins/sample-plugin

# ビルドする
yarn build # yarn
npm run build # npm

# プロジェクトルートに移動し、アプリを起動
cd ../../../
yarn develop # yarn
npm run develop　 # npm

```

管理画面にログインすると左側のメニューから、作成したプラグインが確認できます。

![スクリーンショット 2023-07-06 8.54.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/ba213665-7b2b-b870-08c7-d96081598209.png)


## プラグインの中身を作成する

今回は簡単なボタンコンポーネントを表示させてみます。

`admin/src/components`配下にカスタムボタンコンポーネントを作ります。
```src/plugins/sample-plugin/admin/src/components/Button/index.tsx
import React from 'react';
import Styled from 'styled-components'

const CustomButton = () => {
  return (
    <Button onClick={() => {alert('hello');}}>Button</Button>
  );
}

const Button = Styled.button`
  display: inline-block;
  color: #BF4F74;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid #BF4F74;
  border-radius: 3px;
  display: block;
`;

export default CustomButton;

```


`HomePage/index.tsx`で上記で作成したコンポーネントを表示させます。
```src/plugins/sample-plugin/admin/src/pages/HomePage/index.tsx
/*
 *
 * HomePage
 *
 */

import React from 'react';
import CustomButton from '../../components/CustomButton';

const HomePage = () => {
  return (
    <div>
      <CustomButton></CustomButton>
    </div>
  );
};

export default HomePage;
```

再びビルド・管理画面を起動し、作成されたボタンが表示されればOK！

![スクリーンショット 2023-07-06 9.02.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/27ac0521-a237-291a-4ac8-a13c7f2dd152.png)

## 参考
https://strapi.io/blog/how-to-create-a-strapi-v4-plugin-generate-a-plugin-1-6
React×TypeScriptで、useState<String>('')とするとinputタグのvalueでstateを渡した際にエラーが発生する

# はじめに
ReactとTypeScriptの初心者が、型で苦戦したのでその内容をメモ。
useStateを用いて、入力フォームのvalueを更新していく処理を記述した際にエラーが発生。

# 発生したエラーと解決法
### 修正前のコード
```input.tsx
import React, { ChangeEvent, useState, memo } from "react"

const Input = memo(() => {
    const [ contents, setContents ] = useState<String>('')

    const onChangeContents = (e: ChangeEvent<HTMLInputElement>) => {
        setContents(e.target.value)
    }

    return (
        <input type="text" value={contents} onChange={onChangeContents} />
    )
})
export default Input
```

### エラー内容
```
Type 'String' is not assignable to type 'string | number | readonly string[] | undefined'.
  Type 'String' is missing the following properties from type 'readonly string[]': join, every, some, forEach, and 12 more.
```

### 解決方法
エラー文をよく見ると、「String」型は「string」型に割り当てることが出来ないと書いていました。
該当箇所を見てみると、`const [ contents, setContents ] = useState<String>('')`

「String」型でstateを定義してしまったせいで、inputのvalueに値を入れられなかったのです。
。。。とても初歩的なミスでした（スペルの違いに気付かず、30分も費やしてしまいました。。。）

解決方法としては、該当箇所を以下に変更
`const [ contents, setContents ] = useState<string>('')`

なんなら、`useState('')`で空文字を渡している為、型定義をわざわざ行わなくても暗黙的にstring型になるので、
`const [ contents, setContents ] = useState('')`
こちらでも良いようです。

どちらが良いか分かりませんが、初心者の内は型が明示的に示された方が分かりやすいかなと感じたので、僕の場合は前者で対応しました。
パーセントで実行の進行状況を表示するSwfitUIの非同期処理のサンプル

Swiftでは重たい処理での非同期処理を適切に行わないとViewが実行中に操作不能になります。
以下が簡単なサンプルです。
これを応用すれば重たい変換処理中にユーザーに進捗状況を表示できます。



```Swift

struct ContentView: View {
    @State private var progress: Double = 0.0
    
    var body: some View {
        VStack {
            Text("\(Int(progress * 100))%")
                .font(.title)
                .padding()
            
            ProgressView(value: progress, total: 100.0)
                .progressViewStyle(LinearProgressViewStyle())
                .padding()
            
            Button("Start") {
                startProgress(progress2: $progress)
            }
            .padding()
        }
    }
    
  
    private func startProgress(progress2: Binding<Double>) {
        DispatchQueue.global().async {
            (0..<100).forEach { index in
                sleep(1)
                DispatchQueue.main.async {
                    progress2.wrappedValue += 0.01
                    print(progress2.wrappedValue)
                }
            }
        }
    }
}

```
VSCodeのLiveServer機能を使ってローカルサーバーにスマホからアクセスする方法

# LiveServerとは
VSCodeの拡張機能でWebページ作成をする際に便利なプラグイン
現在作成中のページをローカルサーバー経由でブラウザから開くことができる
さらに、リアルタイムで変更が反映されるからとても便利

# 問題点
Webページ作成をしているときにレスポンシブデザインの対応テストとしてスマホなどのPC以外の別端末で見たいときがあると思います。しかし、通常の設定ではPCで開いているサイトのURLにそのままアクセスしようとするとできないです。今回はURLを変更することによってスマホからURLコピペするだけでアクセスできるようにします。

# やり方
VSCodeの設定を開きます。
「設定の検索」で「liveserver」と打ち込みます。
下へスクロールして「Use Local Ip」にチェックを入れます。
おしまい

# 結果
ブラウザ上に表示されるURLが「http://127.0.0.1:5500/index.html」から「http://192.168.XX.XX:5500/index.html」に変わったと思います。あとはこれにアクセスするだけで別端末からサイトが見れます。

## 追記
Chromeの検証ツールからPC表示とスマホ表示切り替えられるのでそっちのほうが速いです。
高校数学の公式

# 和の公式
和の公式について、あれこれ

数列の和について、公式と呼ばれるものは次にあげるものだろう。

(1): $$ \sum _{k=1}^n 1 = n$$

(2): $$ \sum _{k=1}^n k = \frac{1}{2}n(n+1) $$

(3): $$ \sum _{k=1}^n k^2 = \frac{1}{6}n(n+1)(2n+1) $$

(4): $$ \sum _{k=1}^n k = \bigl [ \frac{1}{2}n(n+1) \bigr ]^2 $$

(5): $$ \sum _{k=1}^n r^{k-1} = \frac{r^n-1}{r-1} = \frac{1 - r^n}{1 -r},\quad (r\neq 1)$$

最後の公式(5)は、等比数列の和の公式である。


ここで$n$の取り得る値は、1以上の整数である。たとえば$n=0$を代入することに意味はない。

$n=0$を(1)-(5)に代入するとゼロになる。これをどのように解釈するべきかは難しいことあるが、
階差数列に対して次のことがいえる。

数列$\{ a_n \}$の階差数列$\{ b_n \}$は、

(6): $ a_n = a_1 + \sum_{k=1}^{n-1} b_k  (n\geq 2)$

という関係をもつ。階差数列が$n$の多項式か指数関数の場合は、(6)は$n=1$の場合にも適用できる。


$$\left( n+1\right) ^{i}-1=\sum ^{i-1}_{k=1}{}_iC_{k}S^{k}$$

# なんかいろいろ

## 指数法則

$a>0$とする。

$$ a^p \cdot a^q = a^{p+q} $$

$$ (a^p)^q = a^{pq} $$

$$ (ab)^p = a^p b^p $$

$$ a^0 = 1 $$

## 絶対値を含む方程式・不等式

$ |x| = c$ の解 $x=\pm c$

$ |x-a| < c$ の解 $-c + a < x < c + a$

$ |x-a| > c$ の解 $x < -c + a$ または $ c + a < x $

## 2次関数のグラフ

方程式$ y = a(x -p)^2 + q ,\quad (a\neq 0)$について、

頂点の座標 $(p,q)$

軸の方程式 $ x = p$


## グラフの平行移動 (一般論)

関数$f(x)$のグラフを与える方程式、$ y = f(x) $に対して、

x軸方向にp, y軸方向にq平行移動させたグラフの方程式

$$ y - q = f(x-a) $$

## 2次方程式

2次方程式
$$ ax^2 + bx + c = 0 , \quad (a\neq 0)$$
について。

解(根)の公式
$$\frac{-b \pm \sqrt{b^2 - 4ac }}{2a}$$

解と係数の関係
$$ x_+ + x_- = -\frac{b}{a} $$, 
$$ x_+ \cdot x_- = \frac{c}{a} $$

判別式
$$ D = b^2 - 4ac $$

### xの1次が偶数の場合

2次方程式
$$ ax^2 + 2bx + c = 0 , \quad (a\neq 0)$$
について。

解(根)の公式
$$\frac{-b \pm \sqrt{b^2 - ac }}{a}$$

判別式
$$ D = b^2 - ac $$

## 正弦定理

$$ \frac{a}{\sin \angle \rm A} = \frac{b}{\sin \angle \rm B}= \frac{c}{\sin \angle \rm C}= 2R $$

## 弦定理

$$ c^2 = a^2 + b^2 - 2ab \cos \angle \rm C $$

## 三角形の面積

$$ \frac{1}{2} ab \sin \theta $$

## 内接円の半径と三角形の面積

$$ \frac{1}{2} r(a+b+c) $$

## 外接円の半径と三角形の面積

$$ abc = 4SR $$

以下のリンク
https://www.evernote.com/shard/s225/sh/c300873f-bacb-4533-bd90-a2675b55201d/a2af50a0d44a53f9/res/1a841c8d-5881-4525-aa2f-fe5278f88a6a/02032014.svg
をはりつけると，画像が表示できる。

![undefined](https://www.evernote.com/shard/s225/sh/c300873f-bacb-4533-bd90-a2675b55201d/a2af50a0d44a53f9/res/1a841c8d-5881-4525-aa2f-fe5278f88a6a/02032014.svg)
ChatGPTとLangChainで履歴書の自己PR文を自動生成

ChatGPTとLangChainの勉強のため、就職面接なんかで提出する履歴書の自己PR文を自動生成するプログラムを作ってみました。


# 機能概要

- 入力項目
    - 応募先企業の説明文
    - あなたの長所
- 出力項目
    - 応募先企業のSWOT分析の予測結果(Strength、Weakness、Opportunity、Threat)
    - 応募先企業が直面している課題の予測結果
    - あなたの履歴書の自己PR文の例（あなたの長所を活用することで、あなたが、応募先企業の課題解決に貢献できることをアピールする内容）

    ```
    入力例：
      応募先企業の説明文：
        設立３年目のベンチャー企業です。従業員数は4名です。
        AI技術を適用した業務システムの実現に向けたPoCおよびシステム開発を行っています。
      あなたの長所：
        自然言語処理分野のAI技術を保有していること、および、
        本番のAIシステムのデリバリ経験を保有していることです。
    ```

    ```
    自己アピール文の出力例：
    私は、自然言語処理分野のAI技術を保有し、本番のAIシステムのデリバリ経験を持つエンジニアです。
    組織[X]の就職面接に応募することで、私の専門知識と経験を活かし、組織[X]の課題の一部に対して
    貢献できると考えています。
    具体的には、AI技術を活用した業務システムの開発において、私の能力を活かすことができます。
    人材不足による業務の遅れや品質の低下に対して、私は豊富な経験を持つことで、効率的かつ高品質
    なシステムの開発を実現することができます。
    ・・・（中略）・・・
    私の能力を最大限に発揮し、組織[X]の成功に貢献できることを信じています。
    ```

# 処理概要

以下のようなステップを踏んで自動生成を行っています。

1. 応募先企業のSWOT分析
    - 「応募先企業の説明文」から、SWOT分析を行う。
2. 応募先企業の課題分析
    - 1.の分析結果から、課題分析を行う。
3. 応募先企業への自己アピール文の生成
    - 2.の分析結果で得られた課題の解決に、「あなたの長所」が貢献できることをアピールする内容の文を生成する。

# 主な利用ライブラリ/サービス

- LangChain
    - PromptTemplate 関連しか使っていません。
- OpenAI の gpt-3.5-turbo

# コード

作成したコードはgithubで公開しています： [kagiya00/sample_resume_generator](https://github.com/kagiya00/sample_resume_generator/)
以下のリンクから google colaboratory 上で実行することもできます： [open in Colab](https://colab.research.google.com/github/kagiya00/sample_resume_generator/blob/main/sample_resume_generator.ipynb)

# 感想

- コードはかなり簡単。
- プロンプトエンジニアリングは、それなりに手間がかかった。
- アイディアが超重要。アイディア次第でかなり高度なことができそう。

以上
TOKEN ECHO Usage 使用法

https://play.google.com/store/apps/details?id=jp.example.mychatgpt&hl=ja-JP

CHATGPTって素晴らしいですね。Androidで使いたくTOKEN　ECHOを作成したのを紹介。
画面は以下のような感じ。（まったく同じではない。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/3fe5808f-177f-33a7-01a6-98d31c3ef3f7.png)

# API keyの取得

OPEN AIにログインし画面右上のPersonalをクリックし「View API Keys」をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/a0f38b6d-b3b0-6879-cc69-a7c89b5634b1.png)

「＋Create new secret key」>「Create secret key」クリックし
APIキーを作成しコピーする。

https://platform.openai.com/account/api-keys
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/14b9a9eb-3ad3-435f-77a5-f1261b78ec60.png)


# 取得したAPI Keyを設定

「TOKEN　ECHO」を起動し右上のスパナマークを押下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/50bf1c8d-063c-e32b-b65d-b94c95784c94.png)

API key paste. 張り付け

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/e063aae2-bcba-515f-fac1-e95aaaa84e2b.png)

Modelを選択する。
7/18時点で最新モデルは「GPT-4」


Press the 'Apply' button
反映するボタンを押す。

# GPT-4 APIが使えない場合
「select model」押下して、GPT-4が表示されていない場合は使えない。

参考：https://auto-worker.com/blog/?p=7919

OpenAIのPlaygroundにアクセスし、Chatモードでモデル項目を選択して
GPT-4が表示されていない場合は使えない。

![python_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/44d3e17e-a59e-1f00-7fb5-001570ddf9a8.png)


# GPT-4 API での画像取り込みについて

2023/3/17 以下で議論されていた？、どうやら未実装のよう・・。
これはぜひ実装して欲しい！。

https://community.openai.com/t/gpt-4-api-and-image-input/102852

GPT-4 API and image input

>Hi there,
>Is there a documented way to supply GPT-4 API with images?
>I couldn’t find anything in OpenAI’s website.

（機械翻訳）
こんにちは、
GPT-4 APIに画像を提供するための文書化された方法はありますか？
OpenAIのウェブサイトでは何も見つけることができませんでした。


>Looks like receiving image inputs will come out at a later time. This is what it said on OpenAI’s document page:
>" GPT-4 is a large multimodal model (accepting text inputs and emitting text outputs today, 
>  with image inputs coming in the future) that can solve difficult problems 
>  with greater accuracy than any of our previous models, thanks to its broader general knowledge and 
>  advanced reasoning capabilities. Like gpt-3.5-turbo , 
>  GPT-4 is optimized for chat but works well for traditional completions tasks."


（機械翻訳） 
おそらく、画像の入力受け取りは後日実現するようです。OpenAIのドキュメントページには以下のように記載されています：
"GPT-4は大規模なマルチモーダルモデルです（現在はテキスト入力を受け付け、テキスト出力を生成しますが、将来的には画像入力も行います）。
    幅広い一般知識と高度な推論能力により、以前のモデルよりも高い精度で困難な問題を解決することができます。
    gpt-3.5-turboと同様に、GPT-4はチャットに最適化されていますが、従来型の補完タスクにも適しています。"
【Jest】import文で『SyntaxError: Cannot use import statement outside a module』が発生するときの対処

## はじめに
Jestでテストを動かそうとしたときに『Jest encountered an unexpected token』や『SyntaxError: Cannot use import statement outside a module』のエラーが発生して、毎度初期設定のやり方をググっている気がするので、n番煎じですがざっとまとめることにしました。

あとこのエラー文での記事がほぼないので、初心者が辿りやすいようにということで。

## 直接原因：JestのデフォルトではESMをサポートしていない
JestではECMAScriptModule (ESM)はまだ実験的なサポートのみで、デフォルトではimport/export文は利用できません。

https://jestjs.io/ja/docs/ecmascript-modules

なので、Babelを使って、Jest実行時のタイミングにCommonJSの形式に変換してあげる必要があります。

## 対処方法
### その１：Babelのインストール
下記コマンドを実行します。
```
$ npm install --save-dev babel-jest @babel/core @babel/preset-env
```

yarnの場合はこちら。
```
$ yarn add --dev babel-jest @babel/core @babel/preset-env
```

### その２：ディレクトリ直下にbabel.config.jsを追加する
新規でファイル作成して、下記を貼り付けします。
```babel.config.js
module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        modules: "false",
        useBuiltIns: "usage",
        targets: "> 0.25%, not dead",
      },
    ],
  ],
  env: {
    test: {
      presets: [["@babel/preset-env", { targets: { node: "current" } }]],
    },
  },
};

```

### その３：テスト実行！
これで通りますね〜
![スクリーンショット 2023-07-12 1.50.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/8cf5cbc1-340b-4ab4-c9f0-a275ce098970.png)


## その他ポイント：package.jsonのtypeには何も指定しない or "commonjs"を指定する
importまわりのエラーが出たので何も考えずにこのあたりをいじりまくったことが記憶にあるのですが、package.jsonのtypeは書かないか、"type": "commonjs"にしましょう。

```json:package.json
{
  "main": "./src/index.js",
  "type": "commonjs",
  "scripts": {
    "test": "jest"
~~~~ 省略 ~~~~
  }
```

## 参考記事
https://qiita.com/riversun/items/6c30a0d0897194677a37
プログレスバーの作り方をメモ：時折現れ、どうつくろうか〜

時々出てきて、どうつくろう〜となるプログレスバーの作り方をメモ
タイトルはChatGPTに任せた結果

# 使ったもの
Rails(7)のテンプレートエンジン
Tailwind CSS

# こう書くと
```erb
<div class='rounded-full w-full h-2 border border-secondary'>
    <div class='bg-secondary h-full' style="width: calc((<%= step %> / 13) * 100%)"></div>
</div>
```
stepが進捗
13は合計のstep数だけれど、直書きせずに`〇〇.size`とかでstepの合計をプログラムで取得して渡した方がstepが増えた時とか不具合が起きなくてすみそう

## こういう感じのものができる

![スクリーンショット 2023-07-10 22.30.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996637/868ea86f-f062-99c3-404f-fb98675fccc5.png)
[Snowflake] SQL100本ノックのコードをSnowflakeで書き換えてみた (50問目までから4問抜粋)

[SQL100本ノック](https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess/tree/master)の問題のうち50問目までをSnowflakeで書き換えるとどうなるか見てみました。50問目までだと、大きく書き方が変化する問題はあまりなかったのですが、縦持ち横持ちの変換が柔軟にできる `PIVOT`, `UNPIVOT` はとても便利に感じました ([S-044の問題がそれです](https://qiita.com/tanif/items/3f51b56b052d4a2952ab#s-044))。 

[SQL100本ノックの全問題はこちらを御覧ください](https://htmlpreview.github.io/?https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess/blob/master/docker/doc/preprocess_knock_SQL.html)
[SQL100本ノックの公式の模範解答はこちらを御覧ください](https://htmlpreview.github.io/?https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess/blob/master/docker/doc/answer/ans_preprocess_knock_SQL.html)

なお、100本ノック用のデータをSnowflakeに入れるのはTroccoを使用しています。
Troccoを使用してデータをSnowflakeのTableに入れるための設定方法はこちらの記事を御覧ください。

[[Snowflake] Troccoを使ってS3にあるデータをSnowflakeに転送してみた](https://qiita.com/tanif/items/717c580b020292ea6958)


# S-028
レシート明細データ（receipt）に対し、店舗コード（store_cd）ごとに売上金額（amount）の中央値を計算し、降順でTOP5を表示せよ。

* Snowflakeでは中央値を計算するための関数 `MEDIAN` があるため、それを使用。
```sql
SELECT 
  store_cd, 
  MEDIAN(amount) AS amount_50per
FROM
  receipt
GROUP BY 
  ALL
ORDER BY
  amount_50per DESC
LIMIT 5
```

# S-044
043で作成した売上サマリデータ（sales_summary）は性別の売上を横持ちさせたものであった。このデータから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を"00"、女性を"01"、不明を"99"とする。

問題がわかりにくいですが、このようなデータ構造のものを
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510106/00c7a8b3-ee55-0821-2c09-d86ba2d43353.png)
こういう構造に変換する問題です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510106/8d675fa5-4543-b31d-2660-a1a74d2eec6c.png)

* Snowflakeでは `UNPIVOT` という、列を行に入れ替える関数があるのでそれを使用。 [(参考)](https://docs.snowflake.com/ja/sql-reference/constructs/unpivot)

```sql
SELECT
  era,
  CASE gender 
    WHEN 'MALE' THEN '00'
    WHEN 'FEMALE' THEN '01'
    WHEN 'UNKNOWN' THEN '02'
  END AS gender_cd,
  amount
FROM
  sales_summary
  UNPIVOT (amount FOR gender IN (MALE, FEMALE, UNKNOWN))
ORDER BY 
  2, 1
```

# S-047
レシート明細データ（receipt）の売上日（sales_ymd）はYYYYMMDD形式の数値型でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号（receipt_sub_no）とともに10件表示せよ。

* Snowflakeでは `列名::VARCHAR` という記法でCASTできる。
```sql
SELECT  
  receipt_no, 
  receipt_sub_no,
  TO_DATE(sales_ymd::VARCHAR, 'YYYYMMDD') AS sales_ymd
FROM
  receipt 
LIMIT
  10
```

# S-049
レシート明細データ（receipt）の売上エポック秒（sales_epoch）を日付型に変換し、「年」だけ取り出してレシート番号(receipt_no)、レシートサブ番号（receipt_sub_no）とともに10件表示せよ。

* Snowflakeでは `EXTRACT` を使わずとも `YEAR` で年を取得できる。 
* `YEAR` に限らず `MONTH`, `DAY` なども同じ様に計算できる [(参考)](https://docs.snowflake.com/ja/sql-reference/functions/year)
```sql
SELECT 
  receipt_no, 
  receipt_sub_no,
  YEAR(TO_TIMESTAMP(sales_epoch)) AS sales_year
FROM receipt 
LIMIT 10;
```
c++ で osc する (oscpack)

(c++ で書けることを python で書くのは情弱だゾ to 自分)

## 背景

自分が c++ 弱くて、osc + c++ の公式??のサンプル↓は動かず、動かし方もあんま書いてなく、サンプルもあんまりシンプルじゃなかったので、デバッグしておれおれシンプル版にまとめてみました。

https://github.com/MariadeAnton/oscpack/tree/master

とりあえず、同じマシン内で文字列の送受信ができることをゴールにしてます。

## 環境
ubuntu 20.04 (on docker)

## 環境構築

g++をまだ入れてない場合は

```shell
sudo apt update
sudo apt install build-essential
```

そして、liboscpackを入れる (← これになかなかたどり着けなかった…)

```shell
sudo apt install liboscpack-dev
```

入れれたか確認

```shell
dpkg -l | grep liboscpack
```


## 送信側

```send.cpp
#include "oscpack/osc/OscOutboundPacketStream.h"
#include "oscpack/ip/UdpSocket.h"
#include <iostream>
#include <string>

#define ADDRESS "127.0.0.1"
#define PORT 7000
#define OUTPUT_BUFFER_SIZE 1024

int main()
{
    UdpTransmitSocket transmitSocket(IpEndpointName(ADDRESS, PORT));

    while (true)
    {
        std::string input;
        std::cout << "Enter a message to send: ";
        std::getline(std::cin, input);

        if (input == "quit")
            break;

        char buffer[OUTPUT_BUFFER_SIZE];
        osc::OutboundPacketStream p(buffer, OUTPUT_BUFFER_SIZE);

        p << osc::BeginBundleImmediate
            << osc::BeginMessage("/test")
            << input.c_str() << osc::EndMessage
            << osc::EndBundle;

        transmitSocket.Send(p.Data(), p.Size());
    }

    return 0;
}
```

## 受信側

```receive.cpp
#include "oscpack/osc/OscReceivedElements.h"
#include "oscpack/osc/OscPacketListener.h"
#include "oscpack/ip/UdpSocket.h"
#include <iostream>

#define PORT 7000

class ExamplePacketListener : public osc::OscPacketListener
{
protected:
    virtual void ProcessMessage(const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint)
    {
        try
        {
            if (std::strcmp(m.AddressPattern(), "/test") == 0)
            {
                osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
                std::string a1 = (arg++)->AsString();
                if (arg != m.ArgumentsEnd())
                    throw osc::ExcessArgumentException();

                std::cout << "received '/test' message with arguments: " << a1 << "\n";
            }
        }
        catch (osc::Exception& e)
        {
            std::cout << "error while parsing message: " << m.AddressPattern() << ": " << e.what() << "\n";
        }
    }
};

int main()
{
    ExamplePacketListener listener;
    UdpListeningReceiveSocket s(IpEndpointName(IpEndpointName::ANY_ADDRESS, PORT), &listener);

    std::cout << "press ctrl-c to end\n";

    s.RunUntilSigInt();

    return 0;
}
```

## コンパイル＆実行！

```shell
g++ -o send send.cpp -loscpack
g++ -o receive receive.cpp -loscpack
```

で実行ファイルができたら、ターミナルを2つ開いておいて、`./send` と `./receive` を実行！

![osc.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188173/9952c335-241f-e845-9575-11d13acd3391.jpeg)

## 以上！
【zsh】正規表現で大文字・小文字を区別させない方法

# はじめに
bashでのやり方と微妙に違い、すぐに忘れるだろうと思ったので備忘として残します。

# TL;DR
- シェルオプション"nocasematch"を使うことで実現可能。
- "nocasematch"は**正規表現使用時**に有効
- 関数内などで一時的に"nocasematch"を使用したい場合は"localoptions"を使う。


## nocasematchをオンにする。

正規表現で大文字・小文字の区別をなくすには、シェルオプションとして用意されている、
"nocasematch"を使用します。

``` zsh
$ setopt nocasematch

#現在のシェルオプションを確認
$ setopt
nocasematch
combiningchars
interactive
login
monitor
shinstdin
zle
```
## if文で使ってみる
``` zsh
if [[ "ABC" =~ abc ]]; then
    echo "Match"
else
    echo "NoMatch"
fi

#出力結果
Match
```
勿論"nocasematch"を外した状態では大文字と小文字が区別されるためelseに処理が流れる。
``` zsh
#nocasematchを予め外しておく
$ unsetopt nocasematch

if [[ "ABC" =~ abc ]]; then
    echo "Match"
else
    echo "NoMatch"
fi

#出力結果
NoMatch
```
### 正規表現でないと機能しない。
このオプションは正規表現でないと機能しないみたいです。
試しに、上記のif文を正規表現を使わずに判定させた場合以下のようになります。
``` zsh
$ setopt nocasematch

if [[ "ABC" = "abc" ]]; then
    echo "Match"
else
    echo "NoMatch"
fi
#出力結果
NoMatch

```
当初はこのオプションを使用するとPowerShellのように完全に大文字・小文字の区別がなくなるものと思っていたので、
個人的にかなり行き詰まったポイントでした。

以下マニュアルの引用です。
> CASE_MATCH <D>
 Make regular expressions using the zsh/regex module (including matches with =~) sensitive to case.

https://zsh.sourceforge.io/Doc/Release/Options.html

## 関数の処理で使う場合は"localoptions"で実行時のみオンにすることも可能

先ほどのif文の処理を関数化します。
関数内で最初に"setopt localoptions nocasematch"でシェルオプションを有効化します。
``` zsh
#関数 nocase-match
function nocase-match () {
	setopt localoptions nocasematch
	if [[ "$1" =~ abc ]]; then
  	echo "Match"
	else
		echo "NoMatch"
	fi
}
```
それでは上記の関数をシェルに読み込ませ、
実行後のシェルオプションの状態を確認します。

``` zsh
#関数を実行
$ nocase-match ABC

#実行結果
Match

#シェルオプションの確認
$ setopt
combiningchars
interactive
login
monitor
shinstdin
zle
```
このように、実行後にはシェルオプションが外れています。
他環境などでの使用を考慮するならば、
このオプションは必須ですね。

# あとがき
やはりzsh関連は日本語の情報が少ないため、
リファレンスマニュアルが頼りになりますね。
Atcoderで入茶しました

色が変わったら記事を書くのが恒例？のようなので、
簡潔ではありますが書きます。


とりあえずレーティングになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855481/915948b1-852b-e01d-e465-397d2625232b.png)

もともとC言語しか触ってこなかったので、
初めのころはすべてC言語で解いていました。

C++の方がライブラリとか色々使えて便利ということだったので、
途中からC++に移行しました。

初めはB問題までしか解けませんでしたが、
DPなどを学び、
そこまで難しくないC問題であれば解けるようにはなりました。

最初の方でレーティングが下がっているのは、
単純に事前にRatedで登録しておきながら、
解くのを忘れ、気づいた時にはコンテストが終了しているという。。。

それ以降はコンテスト直前にRated登録するようになりました。

一度入茶ギリギリのところまではいったのですが、
問題とのかみ合わせが悪く(B問題でもかなり難しいのが出題されたり。。。)、
レーティングが落ちてしまったのですが、
ここ最近の問題ではC問題まで解けたり、
B問題までであっても早く解けたためかつC問題が難易度高かったためレーティングが上がったりで、
結果入茶となりました。

結構時間かかりましたが、何とか入茶できました。

途中、Atcoder Problemというのを知ってからは、
片手間ではありますが、過去問を解いていました。
※C問題は簡単なもののみ、あとはA問題とB問題を難易度が高すぎないものを解いていました。

次は緑ということで、
入緑できるようがんばっていきます。