OmniAICreator/Qiita-1.07M huggingface dataset:
『Missing signing identifier at "/var/folders/....../Frameworks/UnityFramework.framework/Frameworks/libswiftCore.dylib".』が出た時

Unityで作ったアプリをXCodeでDistributeしようとすると

![スクリーンショット 2024-05-05 21.23.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/7572b9ed-36e8-9790-5bfd-035cf485cedc.png)


```
Missing signing identifier at "/var/folders/wy/rj535tcn0xx847cx6v91k_n40000gn/T/XcodeDistPipeline.~~~D37hEU/Root/Payload/DVD.app/Frameworks/UnityFramework.framework/Frameworks/libswiftCore.dylib".
```

が出ることがある

## 対処法
AVFoundation.frameworkを一度削除して、追加し直してDistributeするとうまくいく。

![スクリーンショット 2024-05-05 21.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/bf334caf-a616-1fa1-b62f-5af3ad765a5e.png)
ABC064 の問題を解いてみました

## A問題
https://atcoder.jp/contests/abc064/tasks/abc064_a

3桁の数字は、$100r + 10g + b$ と表せます。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  int r, g, b;
  cin >> r >> g >> b;
  
  int num = r * 100 + g * 10 + b;
  
  if(num % 4 == 0){
    cout << "YES" << endl;
  }
  else{
    cout << "NO" << endl;
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc064/tasks/abc064_b

端から端まで順番にプレゼントを配っていくと、最短距離になります。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  int n;
  cin >> n;
  vector<int> a(n);
  
  for(int i = 0; i < n; i++){
    cin >> a[i];
  }
  
  sort(a.begin(),a.end()); //並び替える
  
  cout << a[n - 1] - a[0] << endl;
  //橋から橋の距離を出力
}
~~~

## C問題
レートが3200以上の人が大きく絡んできます。
色の種類を最大にしたい場合は、存在しない色に3200以上のレートの人を割り振るべきです。
色の種類を最小にしたい場合は、もうすでにある色に割り振るべきです。
(3200以上のレートの人は、黒色なども選べることに注意)

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  int n;
  cin >> n;
  vector<int> a(n), color(8, 0);
  //colorはそれぞれの色が何人いるか記録する配列
  bool ok = false;
  int freedom = 0;
  
  for(int i = 0; i < n; i++){
    cin >> a[i];
    if(a[i] < 3200){
      ok = true;
      //3200以下の人がいない場合への対応
      
      color[a[i] / 400]++;
      //色に下から1,2,...と数字を割り振っておく
      //その色の人の人数を記録する
    }
    else{
      freedom++; //色を自由に選べる人の数を記録しておく
    }
  }
  
  if(ok){
    int kind = 0; //何種類の色の人がいるか数える変数
    for(int i = 0; i < 8; i++){
      if(color[i]) kind++;
    }
    cout << kind << endl;
    
    cout << kind + freedom << endl;
  }
  else{
    cout << 1 << endl;
    cout << n << endl;
  }
}
~~~

## D問題
https://atcoder.jp/contests/abc064/tasks/abc064_d

まず、最初に対応する '(' がない ')' の数を数えて、 '(' を文字列の先頭に挿入します。

そして、 対応する ')' がない '(' の数を数えて、 ')' を文字列の末尾に挿入します。

そうしてできた文字列を出力すればよいです。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  int n;
  string s;
  cin >> n >> s;
  int cnt = 0, ans = 0;
  
  for(int i = 0; i < s.size(); i++){
    if(s[i] == ')'){
      cnt++; //加える必要がある ( の数を数えておく
      
      ans = max(ans, cnt); //最大値を記録しておく
      // 例 )()(
    }
    else cnt--;
  }
  
  for(int i = 0; i < ans; i++) s = '(' + s;
  // ) に対応する ( を s の最初に挿入する
  
  cnt = 0, ans = 0;

  for(int i = 0; i < s.size(); i++){
    if(s[i] == '(') ans++; // 加える必要がある ) の数を数えておく
    else ans--;
  }
  
  for(int i = 0; i < ans; i++) s += ')';
  // ( に対応する ) を s の末尾に挿入する
  
  cout << s << endl;
}
~~~
【個人開発】リアルの友達作りを支援するLINEボットを作りました

## はじめに
非エンジニアのじょうもん([@3dantasymap](https://twitter.com/3dantasymap))です。<br>普段はIT系企業で企画をしています。あと夜間大学の建築学科にも通っています

趣味で個人開発しているので、よかったら仲良くしてください！
## 目次
[1.作った理由](#作った理由)
[2.LINEボットの概要](#LINEボットの概要)
[3.使用した技術](#使用した技術)
[4.こだわり](#こだわり)
[5.おわりに](#おわりに)
## 作った理由
最近コロナが落ち着いて、オフラインのイベントが増えてきました

知らない人たちと対面で会う機会が多くなり、せっかく知り合えた人と仲良くなりたいという気持ちありますよね！

ただコミュニケーションが苦手な私は、対面ですぐに仲良くなることは難しいです・・（得意な人すごい）

SNSとかなら相手の興味と自分の興味が一致しているのを確認して、会話のきっかけが転がってるので問題ないのですが、リアルだと相手の興味がわからないので難しいなあと感じてしまいます

そこでリアルであった初対面のひとと、仲良くなるための共通の興味や趣味に関して、会話のきっかけとなる話題を提供してくれる仕組みがあると便利では！？とおもって作りました

## LINEボットの概要
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647151/8f4efbee-8bf1-62e4-6c2e-795a406b8f75.png" width=100%>

### LINEボットリンク
https://line.me/R/ti/p/@355cawcy?from=page&liff.referrer=https%3A%2F%2Feditor.note.com%2F&accountId=355cawcy

LINEボット「<b>たぐとぴ</b>」は、リアルの出会いを趣味で結ぶということをテーマにした会話支援サービスです

事前にボット内で興味タグを登録し、自動で生成されるQRコードを読み取ることで、お互いの共通の興味について盛り上がる話題を提案します

ジャンルごとに表示されるタグが変わるため、選びやすい設定になっています

## 使用した技術
LINE Messaging API
LIFF
Firestore
Functions
chatGPT
QRcode.js

html/css/javascriptで作成しました！
LIFFやfirebaseがあるおかげで、プログラミングに慣れないながらも比較的簡単につくれました(/・ω・)/

## こだわり
特にこだわった点は、ジャンル選択画面の選びやすさです！
既存のマッチングアプリを参考にして、わかりやすい選択画面をめざしました

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647151/b0e4beb2-e48d-9dff-0052-4c6c3f31948a.png" width=50%>

あとはLINEボット内で完結するように、タグ登録とQRコードの表示画面をメニューにわかりやすく表示させたことです。親しみやすいデザインを心掛けました

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647151/1795de7a-e272-36da-df96-5bd2b3401b81.png" width=50%>

あとはchatGPTが話題として適したものを出力するためのプロンプトを何度も調整しました・・

## おわりに

拙い文章を読んでいただきありがとうございました！

もしよかったらXやっているので交流してもらえると嬉しいです

https://twitter.com/3dantasymap

また、今回せっかく作ったので[LINE DC BOT AWARDS 2024](https://lineapiusecase.com/ja/community/linedc-award-2024.html)に応募してみました

youtubeでイベント見たけどすごいひといっぱい・・入賞できるといいなあ～～
日付や時間の取り扱いについてうす〜く調べてみた〜その１

# 書こうと思ったきっかけ
前にも書きましたが、自転車のレース運営をお手伝いしてるんですよ。
でね、タイムトライアルって種目があって、一人ずつ走ってタイムを競うんです。そう、走行時間を計測しなきゃいけないんですね。
で、最近、Google Apps Scriptで計算するようにしたんですが、まぁ時間関係に手間取りました。
そんな時にPythonでも時間を扱う事例が発生したのでまとめて書いとけや！と思ったわけです。
つまり、「**共通点があるならまとめてやった方が効率的じゃん**」です。

あ、そうそう、前提がひとつ。ここではjavascriptでもpythonでもexcelでも日付、時間を扱う型を**datetime型**と呼んでます。
正式には違うのかもしれないけれど、面倒なんでご容赦を。

<br>
<br>

# ISO8601　（日付と時刻の表記に関するISO）
ま、今日まで知らなかったですよ。本当に。
基礎の「き」は真面目にやっていた方がいい。

https://ja.wikipedia.org/wiki/ISO_8601

<br>
<br>

### 基本形式と拡張形式
とはいえ、皆さんも忙しいでしょうし、僕なりに気になったところをピックアップしとくね。

https://ja.wikipedia.org/wiki/ISO_8601#%E5%9F%BA%E6%9C%AC%E5%BD%A2%E5%BC%8F%E3%81%A8%E6%8B%A1%E5%BC%B5%E5%BD%A2%E5%BC%8F

特に拡張形式だけでも覚えちゃおう
`YYYY-MM-DDThh:mm:ss+09:00`とか`YYYY-MM-DDThh:mm:ssZ`
Zをつける時はUTC（協定世界時；Universal time corrdinated）です。

`T`で区切って、左には年月日を`-`で繋ぐ、`T`の右は時間分秒を`:`で繋いで、最後にUTCからの時間差を書く。
<br>
<br>

# まずは公式ドキュメントの紹介
Pythonは`datetime`、JavaScriptは`Date`オブジェクト。
正直言って、僕もまだまだよくわかっていない。言葉が難解。

- Python

https://docs.python.org/ja/3/library/datetime.html#module-datetime

- JavaScript

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date

はい。皆さんしっかり読めば大丈夫（お前はど〜よって言われそう。汗）
ええ、充分にはわかっていません。

<br>
<br>

### datetime型の基本の「き」
これさえわかればあとは何とでもなると思います。

先に紹介したJavaScriptのMDNのページの最初の方をよく読んでみてください。こう書いてあります。

```
JavaScript の Date オブジェクトは、単一の瞬間の時刻をプラットフォームに依存しない形式で表します。 
Date オブジェクトは協定世界時 (UTC) の 1970 年 1 月 1 日からの経過ミリ秒数を表す Number の値を含んでいます。
```
はい、今日の大事なところはここまでです。
`え？`っと思われるかもしれませんが、これさえ知っておけばあとは応用でどうにかなります。

<br>

### 「今」の日付を確認してみる

- Python

```python
now = datetime.datetime.now()
print(now)
print(now.timestamp())
```

```
2024-04-26 22:31:25.627429
1714138285.627429
```
<br>

- JavaScript
```JavaScript
let now = new Date();
console.log(now);
console.log(now.getTime());
```

```
Fri Apr 26 2024 22:37:36 GMT+0900 (日本標準時)
1714138656650
```

で、気づくとこありません？？？
そう、`timestamp()`とか、`getTime()`とかの出力です。
流石に同時に出力は無理でしたが、数字を並べてみましょう。


    1714138285.627429　　　（Python）
    1714138656650　　　　　　　　　　　（JavaScript）

あれ、大半の桁が同じ・・・。
そう、上でMDNの文章を引用しましたが、いずれも**1970年1月1日の0時0分0秒**を基準にしてるんですね。
ただし、Pythonは単位が秒、JavaScriptはミリ秒ってところに気をつけてください。pythonは小数点以下が６桁あるのでマイクロ秒まで計算してるんですね。

<br>
<br>

# ちょっと道を逸れてExcel

ちなみにエクセルはどうなっているかというと1900年1月1日が`1`で、**日付**が増えるごとに１増えるとか。

https://excelcamp.jp/media/function/10664/

Python、JavaScript、Excelまじバラバラやん。w

一応試す
![スクリーンショット 2024-04-30 22.55.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655320/46aee172-ec70-4314-f835-eebc9489ec55.png)

文字列として`2024年4月26日`その右側のセルに`=DATEVALUE(ひとつ左のセル)`
出力は`４５４０８`
ちなみに小数点があると時間を表現できるんだと。1/24が1時間分で、1/(24*60)が1分ぶん。

**ここまで三つの言語ともにバラバラ。ああ、めんどい。まじめんどい。**


<br>
<br>

# 大事なこと

大事なことはdatetimeってのは言語によって設定が違うし、バラバラだし、  
でも、どっかに基準の日時があって、数える単位も違うんだけど、時間が経つとカウントアップしていく

そんな感じのことを理解しおけばいいってことよね？（PythonとJavaScriptとExcelだけで偉そうなこと言ってる。w）


# と言うことで・・・
今日は酔ってしまったので、具体的な使い方はその２以降で紹介できれば（私が復習できれば）と思っています。
楽しかった日はお酒が美味しいので酔ってしまうのは仕方がない・・・うん、仕方がない。
ml5.js の FaceApi（face-api.js の一部の機能を使える API）で扱える仕組み・モデルに関するメモ

## はじめに
JavaScript で手軽に機械学習を扱える「ml5.js」の「FaceApi」に関するメモです。

●FaceApi
　https://learn.ml5js.org/#/reference/face-api

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/4bf25ba1-72be-e761-14c3-148156e2cc16.png)

### 記事を書いた経緯
ml5.js の公式リファレンスを眺めていて、ふと FaceApi の内容が目にとまり、この FaceApi の内容はあまり詳しく見たことがなかったので、あらためて見てみたというのがこの記事を書いた流れです。

## 注意が必要な部分
ml5.js の FaceApi は、その元になっている「face-api.js」の全機能を使えるわけではなく、一部の機能のみを使えるもののようです。

具体的な内容は、トップページの以下の部分に書いてあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f9313c0a-d993-9190-57ef-07e6bb7754b9.png)

「does not support **expressions, age or gender estimation**.」と書かれているように、以下の中の「Face Expression Recognition」「Age Estimation & Gender Recognition」は扱えないようです（以下の中の「Face Recognition」「Face Landmark Detection」のみに対応しているようです）。

●justadudewhohacks/face-api.js: JavaScript API for face detection and face recognition in the browser and nodejs with tensorflow.js
　https://github.com/justadudewhohacks/face-api.js/tree/master

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7a3d1764-ad55-a78b-8bff-88c8b47f960d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/77156f3b-2f53-d516-2ed5-1981969e75f1.png)

### 【追記】 非公式のバージョンで上記の機能に対応したものがありました
上で、公式の ml5.js だと対応していない機能がある、という話を書いていました。

その話について、非公式のもの（ml5.js に手が加えられたバージョン）で、上記の機能に対応したものがあるのを発見しました。詳細は、以下の記事をご覧ください。

●ml5.js の FaceApi で face-api.js の表情認識などの対応が組み込まれたものがあった - Qiita
　https://qiita.com/youtoy/items/f942fc997e0b05d90495

## ml5.js の FaceApi で扱えるモデル
ml5.js の FaceApi の説明を見ていると、扱えるモデルは以下に書かれた 5つになりそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/5b6c8464-3ab9-5360-cadd-b1ad6a829b17.png)

ちなみに、face-api.js のほうで扱うことができるモデルは、[公式情報](https://github.com/justadudewhohacks/face-api.js/tree/master?tab=readme-ov-file#loading-the-models)を見ると以下となっているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/de1b6400-29b7-3f90-655b-747819c14259.png)

```javascript
console.log(faceapi.nets)
// ageGenderNet
// faceExpressionNet
// faceLandmark68Net
// faceLandmark68TinyNet
// faceRecognitionNet
// ssdMobilenetv1
// tinyFaceDetector
// tinyYolov2
```

それらを比較すると、利用できないモデルは「ageGenderNet」「faceExpressionNet」「tinyYolov2」となるようです。
wsl2のubuntuでprivate local networkから変更 (bridgeモードへ)

# bridge modeに変更する

1. Hyper-V managerを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/3a268111-555d-9d95-3866-66fc7fa506b6.png)
1. local machineに接続
1. 仮想スイッチマネージャーに接続 <br> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/83cf17d0-ab26-b0b0-ea57-cec4162f91ad.png)
1. 新しい仮想ネットワークスイッチで、外部ネットワークを作成 <br> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/a732ee17-0a19-d110-df1a-ecf41644b38e.png)
1. 名前をつけて保存 <br> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/a95a1921-3b92-4925-18ba-d4f84af64312.png)
1. .wslconfig を作成 <br> ```.wslconfig
[wsl2]
networkingMode=bridged
vmSwitch=external
dhcp=true
localhostForwarding=True```
1. wsl2を再起動 <br> ```wsl --shutdown```

# おまけ

## hostnameの変更

```/etc/wsl.conf
[network]
hostname = wsl
```
でwslのhost名を変更できる

```sudo hostname wsl``` みたいに変更しても毎回忘れてしまうが、上で変更すればOk

## avahiのinstall

```
sudo apt install avahi-daemon
sudo systemctl start avahi-daemon
sudo systemctl enable avahi-daemon
sudo ufw allow mdns
```

これで、例えば、wsl.localでhost解決ができます.
Redux 調べてみた編

# 目的
Reduxの大まかな状態の管理方法や構成要素を把握すること

# Reduxとは
状態管理を容易に行うライブラリ

## 状態とは
チェックボックスがチェックされているなどのアプリケーションが持っている情報

# Reduxを構成する3要素
## store
状態を保持しているオブジェクト
## action
アプリケーション内で起きたことを説明するためのイベント
## reducer
storeとactionから必要に応じてstoreを更新し、新しい状態を返す関数

# 特徴
すべてのデータへの変更をアクションとして記述する
→いつ、どこで、なぜ状態が変化したのかがわかりやすい

Redux DevTools Extensionを使用すると状態の変化を時系列で追うことができる

# Reduxの3原則
- 信頼できる唯一のデータソース
- stateは読み込み専用
- 変更は純粋な関数で行う

# dispatch
アクションオブジェクトをstoreに送る
storeではアクションオブジェクトと状態がreducerに渡され、reducerは新しい状態を返す

# 参考文献
Redux公式
https://redux.js.org/

Redux 入門 〜Reduxの基礎を理解する〜
https://qiita.com/soarflat/items/bd319695d156654bbe86
配列やListの要素を1行でコンソールに表示

## 0.0 はじめに
Unityのゲーム作成用に使用するC#スクリプトでの小ネタです。

## 1.0　string.Join関数
string.Join()を使用すると配列やList内の要素を1つの文字列にまとめることができます。
区切り文字となる第一引数は変更可能です。

## 2.0　コンソールに表示
まとめた文字列をDebug.Log関数でコンソール表示すれば完了です。

もちろんstring.Join()はコンソールに表示すること以外にも使えます。

```C# Test.cs
string[] array = new string[] {"リンゴ", "めろん", "banana" };
Debug.Log( string.Join(" , ", array));
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352037/306c4820-3987-de92-7a65-c3555ba6ff94.png)
　

intの配列やListの場合もstring型で表示できます。
```C# Test.cs
List<int> list  = new List<int> {555, 22, 012 };
Debug.Log( string.Join(" , ", list));
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352037/43197206-a6bc-3b94-7871-0c7d47f7565d.png)
【Go言語学習】goroutine (ゴルーチン)

# A Tour of Goでの説明
Goroutines
goroutine (ゴルーチン)は、Goのランタイムに管理される軽量なスレッドです...
https://go-tour-jp.appspot.com/concurrency/1

# ザックリとした現状の理解
Goにおける並行処理の機能で、軽量、非同期的に複数のスレッドを容易に実行できる。
共有メモリへのアクセスは同期する必要がある。

# 動作の現状の理解
main()が終了すると、ゴルーチンも終了する。
論理的なスレッドであるものの、並行処理（Concurrency）と並列処理（Parallelism）の概念がある様で、裏っ側ではCPUにも依存する部分もある模様。
非常に軽量で何百万ものスレッドを同時に使える。

# ゴルーチン指向
https://github.com/kabasunny/GoPractice/tree/develop/goroutines
```Go
package main

import (
	"fmt"
	"sync"
	"time"
)

func say(s string, wg *sync.WaitGroup) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
	wg.Done() // 終了したらDoneを呼び出すことで、Addで渡した数字が‐1される
}

func main() {
	var wg sync.WaitGroup // WaitGroupを作成
	wg.Add(2)             // 待つゴルーチンの数を2つ増やす
	go say("world", &wg)  // ゴルーチンを立ち上げ、WaitGroupを渡す
	say("hello", &wg)     // メインゴルーチン？
	wg.Wait()             // 全てのゴルーチンが終了するのを待つ
}

/* A Tour of Goのコード
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}
*/

```
Rustのチャンネルでエラトステネスの篩、async版

# エラトステネスの篩 async版

下の記事のつづき。

https://qiita.com/hidemotoNakada/items/f44b66d39c8e8a190e0a

Threadで書いていたものをCoroutineというか、async/awaitで書き直す。

まずは `tokio` と `futures` を使うので、`Cargo.toml` に下記を追加。
``` toml
[dependencies]
tokio = { version = "1", features = ["full"] }
futures = "0.3"
```

ロジックは同じ。async/await の動作機構は、スレッドとはまるで違うはずなのだが、tokioを使うとかなり普通に使える。異常だ。
チャンネルを使う際に `tokio::sync::mpsc::channel` を使うこと。こちらの `Receiver` は `iter()` がないので、1つずつ`recv` してやらなければならないところが、違うといえば違う。

``` Rust
use tokio::sync::mpsc;
async fn async_prime(n: i32) {
    let (numbers_in, to_sieves) = mpsc::channel(1);
    let (result_stream, mut result_out) = mpsc::channel(1);
    tokio::spawn(async move {
        async_sieve(to_sieves, result_stream).await;
    });
    tokio::spawn(async move {
        for i in 2..n {
            numbers_in.send(i).await.unwrap()
        }
    });

    let mut res: Vec<i32> = Vec::new();
    while let Some(one) = result_out.recv().await {
        res.push(one);
    }
    println!("Received {:?}", res);
}

#[tokio::main]
async fn main() {
    async_prime(1000).await;
}
```

## 再帰関数のasync化

篩のほうの関数はちょっと面倒。普通に `async fn` では書けない。`async` で直接再帰関数を定義すると、関数の型が無限にネストしてしまうかららしい。

以下の記事に詳しい。
https://rust-lang.github.io/async-book/07_workarounds/04_recursion.html

回避策としては、`async fn` としてではなく、`Box` された `Future`を返す、通常の関数として定義すればいい。

``` Rust
use futures::future::{BoxFuture, FutureExt};

fn async_sieve(mut in_stream: mpsc::Receiver<i32>, result_stream: mpsc::Sender<i32>) 
-> BoxFuture<'static, ()> {
    async move {
        if let Some(prime) = in_stream.recv().await {
            result_stream.send(prime).await.unwrap();
            let (tx, rx) = mpsc::channel(1);
            tokio::spawn(async move {
                async_sieve(rx, result_stream).await;
            });

            while let Some(i) = in_stream.recv().await {
                if i % prime != 0 {
                    tx.send(i).await.unwrap();
                }
            }
        }
    }.boxed()
}
```

あちこちに`.await` が挟まってちょっとうざいぐらいで、基本的には同じ。

## 不思議

`std::sync::mpsc::Receiver` の `recv` は、
``` Rust
fn recv(&self) -> Result<T, RecvError>
```
と定義されていて、引数が不変参照で、返り値`Result`なのに、

`tokio::sync::mpsc::Receiver` の `recv` は

``` Rust
async fn recv(&mut self) -> Option<T>
```
となっていて、 引数が可変参照で、返り値も`Option`。

なぜ?

### Async フィボナッチ

テスト用に書いたフィボナッチもついでに掲載しておく。これであってるのかなあ。

``` Rust
use tokio::sync::mpsc;
use futures::future::{BoxFuture, FutureExt};

fn async_fib(n: i64) -> BoxFuture<'static, i64> {
    async move {
        if n > 2 {
            let f1 = tokio::spawn(async move {async_fib(n-1)}).await.unwrap();
            let f2 = tokio::spawn(async move {async_fib(n-2)}).await.unwrap();
            f1.await + f2.await
        } else {
            1
        }
    }.boxed()
}

#[tokio::main]
async fn main() {
    let n = 30;
    println!("fib {:} {:?}", n, tokio::spawn(async move {async_fib(n)}).await.unwrap().await);
}
```
PDF 上の領域を PNG に切り出す (+ PDF 上の文章と図を列挙する) 

PDF 上の領域を PNG ファイルに切り出すだけです。
やっていることは、[pdf2image](https://pdf2image.readthedocs.io/en/latest/reference.html) によって対象ページの画素の Numpy 配列を得て、ほしい領域にスライスして、PNG ファイルにかきだしているだけです。

主な用途として、pdfminer.six と組み合わせて利用することを想定しています (「経緯とおまけ」を参照)。

### スクリプト

以下で out.png が切り出せます。
動作確認したい場合は https://arxiv.org/pdf/2302.11939 をダウンロードして隣に置いて実行すれば 2 ページ目の図が切り出されると思います。

```py
from pdf2image import convert_from_path
# Pillow か cv2 のどちらかあればよいが pdf2image が Pillow 依存のため Pillow のほうがよかった
from PIL import Image
# import cv2
import numpy as np


# PDF の指定のページの指定の座標を PNG に切り取ります
def extract_image_from_pdf(
    pdf_file_path,  # 入力 PDF ファイルパス
    i_page,  # 何ページ目か (最初のページが 1 ページ)
    width, height,  # ある座標系でのページ横幅とページ縦幅
    x0, x1, y0, y1,  # その座標系での切取領域 (ページ左下が原点)
    out_path='out.png',  # 出力 PNG ファイルパス
):
    pdf_imgs = convert_from_path(
        pdf_file_path, first_page=i_page, last_page=i_page)
    img_arr = np.asarray(pdf_imgs[0])
    height_ = img_arr.shape[0]
    width_ = img_arr.shape[1]
    left = int(width_ * (x0 / width))
    right = int(width_ * (x1 / width))
    top = int(height_ * (1.0 - y1 / height))
    bottom = int(height_ * (1.0 - y0 / height))

    # PIL の場合
    im = Image.fromarray(img_arr[top:bottom, left:right])
    im.save(out_path)

    # OpenCV の場合： RGB --> BGR にする必要があるため逆順にしてかきだす
    # cv2.imwrite(out_path, img_arr[top:bottom, left:right, ::-1])


extract_image_from_pdf(
    '2302.11939v6.pdf', 2, 612, 792,
    147.59897250019998, 497.5777438482, 497.2811145825, 727.2735377315)
```

### 経緯とおまけ ( pdfminer.six で PDF 上の要素を列挙する)
[pdfminer.six](https://pdfminersix.readthedocs.io/en/latest/) は PDF の各ページのどこの座標にどんな文章や図があるかを解析してくれるパッケージです。が、図の扱いはややこしいと思います。

というのは、対象ページ LTPage 以下に LTImage オブジェクトがぶらさがっていればそれを画像ファイル化できますが ( [python - Pdf miner how to extract images - Stack Overflow](https://stackoverflow.com/questions/68891001/pdf-miner-how-to-extract-images) )、対象ページ中の図が必ずしも LTImage として取得できずに線 (LTLine) や曲線 (LTCurve) の集合になっていることがあります (この記事のスクリプトで抜き出した絵はそうなっています＝LTFigure 以下に LTImage がないです) (同じ PDF 内でも LTImage として取り出せる図もあります) (なお、LTLine や LTCurve が簡単に画像ファイル化できないのかはよく調べていません)。

なので、pdfminer.six によって図を抽出するのはあきらめて、LTFigure 領域をみつけたらそのページの画素からその部分の画素を切り取ることにしました。そうすると下のキャプチャのように、左側の PDF ページから、右側のような「このページのどこに図と文章がある」という情報を列挙できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/05f7801c-d71b-5f0a-63f3-3c7ca5aebd63.png)

上のキャプチャのスクリプトは以下のノートブックの 2 セル目です (Gist には画像は表示されません)。なお、このスクリプトは LTPage 直下の LTTextBox と LTFigure しか抽出しません。 
[https://gist.github.com/CookieBox26/e4b3c83f728a421760ebb81faf7a24f8](https://gist.github.com/CookieBox26/e4b3c83f728a421760ebb81faf7a24f8)
ABC352回答メモ

# 0.はじめに
　GWの半ばの冠スポンサー無しの開催。
 難易度はそこそこでしたが、Dまで解け、久々にレート+7と
 微増で836となりました。


# 1.A - AtCoder Line
　XYZの大小関係を判別する問題。
 XとYの小さい方をA、大きい方をBとし
 ZがＡとＢの間であるかを判別しました。

　https://atcoder.jp/contests/abc352/submissions/53086664


# 2.B - Typing
　なかなかややこしい問題。
 Whileをつかうかforをつかうかーと迷いつつ
 forでSの文字列をINDEX_iで頭から見ていき
 T用のINDEX_jは別に準備しておいて
 S[i]とT[j]の値が一致するまでjを加算していき
 一致したら 回答用リストにj+1を追加
 最後に回答用リストを出力して終了。
 で、行けました。

　https://atcoder.jp/contests/abc352/submissions/53097350


# 3.C - Standing On The Shoulders
　Cの割には簡単な問題。
 若干問題文がややこしく感じましたが、最終的には
 全員の足から肩までの長さの合計と誰か一人の頭の長さを足したものが
 答えとなる為、Aの合計と、B-Aのマックス値を足したものを出力して
 正解となり巻いた。

　https://atcoder.jp/contests/abc352/submissions/53104837


# 4.D - Permutation Subsequence
　問題文を読み込んで例題をみてやっと何を言っているかわかりました。
 与えられたリストの中でK個の連続数が入る範囲が一番狭い幅は
 何個分か？という問題でした。
 最小値としては、K-1となります。
 【考え方】
 　・数列の値をキー、位置を値にセットした辞書を作成
   ・値１から順にK個分、辞書で調べた位置をソーテッドリストSに格納していく
   ・K個分溜まって以降は、値iの位置を追加したら、i-Kの値をSから除外していく
   ・S内にK個溜まって以降は（はじめは１～Kの位置）Sの末尾の数から先頭の数を引いた値と
　　 変数ansの小さい方をansにセット
　　・最後にansを出力
　ややこしくはありましたが、問題の意図が分かればなんとかなる問題でした。

　https://atcoder.jp/contests/abc352/submissions/53125689


以上
【Laravel】Password::defaults()でバリデーション

# 開発環境

Laravel10
Windows11

# 目的
アプリケーション作成時にパスワード検証を何度も行うため、何度も同じ処理を書くのがめんどい。

→デフォのパスワードルールを作成。


# 公式ドキュメント

https://laravel.com/docs/8.x/validation#validating-passwords

# 設定可能な項目
```php:
// 最低8文字
Password::min(8)

// 1文字以上のアルファデットを含む
Password::min(8)->letters()

// 大文字と小文字のアルファベットを含む
Password::min(8)->mixedCase()

// 1文字以上の記号を含む
Password::min(8)->symbols()

// 漏洩済みパスワードでないか
Password::min(8)->uncompromised()
```
※上記はほぼ引用
[引用：https://zenn.dev/nshiro/articles/e6549d83211363]

# AppServiceProvider
AppServiceProviderのboot()で実装。
```php:AppServiceProvider.php
use Illuminate\Validation\Rules\Password;

    public function boot(): void
    {
        return Password::min(8)->letters()
                                ->mixedCase()
                                ->numbers()
                                ->symbols()
                                ->uncompromised();
    }
```

# 本番環境
```php:AppServiceProvider.php
public function boot()
{
    Password::defaults(function () {
        $rule = Password::min(8);
 
        return $this->app->isProduction()
                    ? $rule->mixedCase()->uncompromised()
                    : $rule;
    });
}
```
`$this->app->isProduction()`で現在の実行環境が本番環境であるかを判定。

判定基準は`.env`の`APP_ENV`。
下記の記述になっている場合は、本番環境と認識する。
```
APP_ENV=production
```
# Request
設定したデフォのルールは下記の通り記述することで適用される。
```php:TestRequest.php
    public function rules(): array
    {
          'password' => ['required', 'confirmed', Password::default()],
    }
```

# 参考記事

https://zenn.dev/nshiro/articles/e6549d83211363

https://zenn.dev/nshiro/articles/50a04a9e62cc2b
main branch にコミットしてしまった時の対処法

新しいブランチを作成せずにコミットしてしまい慌ててしまったので備忘録

## 手順
① 新しいブランチを作成する
```
git checkout -b foo
``` 

② main branchに切り替える
```
git checkout main
```
③ コミットを取り消す

```
git reset origin/main --hard
```

## コマンド内容
- git checkout ブランチ名：ブランチを切り替える
  
- git checkout -b ブランチ名：-b はブランチを新規作成なので、ブランチを新規作成してブランチを切り替える
  
- git reset --hard：コミット内容すべてを取り消す
ペイドソースソフトウェアという考え方について

どうも。明日が来てほしくないと切に願っているメンヘラです。(酒に酔った勢いで)さて・・・

# こんな事件をご存じだろうか

開発者MはOSSでソフトウェアやライブラリを作っていた。彼のOSSのソフトウェアやライブラリは非常に良質で、多くのOSSソフトウェアがこれに依存するようになった一方、彼に入る金銭は少なかった。金銭が原因かどうかはさておくとして、彼は自身のOSSプロジェクトにちょっとしたコードを仕込み、もうOSSに貢献しない事を表明した。彼のOSSプロジェクトは他の人が管理する事になった。

# この事件の私的考察

MはOSSに多大な貢献をしたにも関わらず、その功績が金銭として現れなかった。言い換えれば、MのOSSのコードは企業にとって、あるいは個人にとって価値のないものだと **見なされた。** つまり、企業や個人はOSSのコードの価値を、たとえ彼らがOSSに貢献していたとしても、十分に理解していない。

# どのようにして、企業や個人にOSSのコードの価値を理解させるか

オープンソースは以下を全て満たしたプログラムを言います。

- プログラムのソースコードが自由に利用できる
- プログラムのソースコードを自由に頒布(or 再頒布)できる
- プログラムのソースコードを自由に改変できる

しかしここには、「無料で」という要件は含まれない事に留意しましょう。

・・・お気づきになられたでしょうか？仮にプログラムのソースコードの利用、頒布、改変によって発生する金銭的利益がOSS開発者に渡れば良いのです！！

# 準OSSという考え方

そしてここで本題。じゃあ実際に金銭的利益をOSS開発者に分配するにはどうすれば良いのか思案した結果、プログラムのソースコードのサブスクリプションというアイディアに行き着いた。つまり、以下の条件を満たすようなプログラムの利用規定があれば良いのです。

- 利用者は開発者に月額料金を支払う事で、プログラムのソースコードを自由に利用できる
- 利用者は月額料金を支払っている限り、利用者は開発者が更新した最新のプログラムのコードを自由に利用できる。
- 利用しているプログラムのソースコードは自由に改変できる。
- 利用しているプログラムのオブジェクトコードを含む、あるいはリンクしているオブジェクトコードは自由に頒布(or再頒布)できる。
- ただし、利用者は利用しているプログラムのソースコードを自由に頒布(or 再頒布)することはできない。これを認めると、利用者が開発者のソースコードを無料でミラーリングする事を許してしまうためである。

これらの要件は非常にオープンソースに近いですが、プログラムのソースコードを自由に頒布ないしは再頒布できないという点で、オープンソースではありません。そこで、上記要件を満たすようなソフトウェアを~~準OSS~~ Paid Source Software (PSS)と言いたいです。(お気持ち表明)

# 終わりに

オープンソースソフトウェアは便利な反面、金銭的価値や技術的価値が過小評価される傾向が強いように感じます。僕は、感覚的ではありますが、エンジニアの採用活動を行っている企業の99.95%はコードどころか、Githubのプロファイルページすら見ていないのではないかと疑ってしまうほどです。そんな中で、あなたはOSSに貢献する価値を、見出すことはできますか？

## ちなみに・・・

上記の構造を実現するためにGithubやGitlabでは細かいパーミッションの設定が必要です・・・が、それをするにも金が要るようでした。共産主義バットをぶん投げたい所ですが、GithubやGitlabもそのプラットフォームの維持に金銭が必要であるという事を改めて自覚させられました。

~~やはり金！資本主義では金が全てを解決する！~~
ABC063 ARC075 の問題を解いてみました

## A問題
https://atcoder.jp/contests/abc063/tasks/abc063_a

愚直に実装しましょう。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  int a, b;
  cin >> a >> b;
  int ans = a + b;
  
  if(ans >= 10){ //10以上か判定する
    cout << "error" << endl;
  }
  else{
    cout << ans << endl;
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc063/tasks/abc063_b

出現したアルファベットを記録しておいて、記録しておいた文字が出てきた場合noになります。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  string s;
  cin >> s;
  
  vector<bool> ok(26, false);
  //出現したアルファベットを記録する配列
  
  for(int i = 0; i < s.size(); i++){
    if(ok[s[i] - 'a']){ // char - char で char を数字に直せる
      cout << "no" << endl;
      return 0;
    }
    else{
      ok[s[i] - 'a'] = true;
    }
  }
  cout << "yes" << endl;
}
~~~
~~~C++:別解
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  string s;
  cin >> s;
  
  for(int i = 0; i < s.size(); i++){
    for(int j = i + 1; j < s.size(); j++){
      if(s[i] == s[j]){
        cout << "no" << endl;
        return 0;
      }
    }
  }
  cout << "yes" << endl;
}
~~~

## C問題
https://atcoder.jp/contests/abc063/tasks/arc075_a

まず、試験システムの欠陥を考慮せずに、すべての問題に正解した場合の点数を考えます。
その点数が10の倍数の場合は、試験システムの欠陥のために、10の倍数から抜け出したいです。

10の倍数から抜け出すには、10の倍数以外の数を引けばよいです。
10の倍数でない最も低い問題の配点を引けば答えが求められます。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

signed main(){
  int n;
  cin >> n;
  vector<int> s(n);
  int sum = 0;
  
  for(int i = 0; i < n; i++){
    cin >> s[i];
    sum += s[i]; //すべての問題の合計点を求める
  }
  
  int ans = 0;
  
  if(sum % 10 != 0){ //合計が十の倍数でないなら
    ans = sum;
  }
  else{
    sort(s.begin(), s.end()); //ソート
    for(int i = 0; i < n; i++){
      if(s[i] % 10 != 0){ //10の倍数でないなら
        ans = sum - s[i];
        break;
      }
    }
  }
  cout << ans << endl;
  
}
~~~

## D問題
https://atcoder.jp/contests/abc063/tasks/arc075_b
覚えるのは必須じゃないけど役に立つもの 〜 2の冪（べき） 〜

## はじめに

 読了時間：5分

覚えてなくても問題はないけど、覚えていて損はないことを小出しに紹介して行こうかと思います

## **2の冪（べき）と近似値**

今回は **2の冪（べき）と近似値**です。

以下のようなケースで役に立つかと思います。
- スケーラビリティやメモリの制限があるような問題に向き合う時
- Intなど数値型ではどの数値まで扱えたか？

<table>
  <caption>2の冪（べき）の表</caption>
  <thead>
    <tr>
      <th>2の冪</th> <th>厳密な値</th><th>近似値</th> <th>MB, GBなど</th>
    </tr>
  </thead>
  <tr>
    <td> 7 </td> <td>128</td><td> - </td> <td>-</td>
  </tr>
  <tr>
    <td> 8 </td> <td>256</td><td> - </td> <td>-</td>
  </tr>
  <tr>
    <td> 9 </td> <td>512</td><td> - </td> <td>-</td>
  </tr>
  <tr>
    <td> 10 </td> <td>1,024</td><td> 千 </td> <td>1 KB</td>
  </tr>
  <tr>
    <td> 16 </td> <td>65,536</td><td> - </td> <td>64 KB</td>
  </tr>
  <tr>
    <td> 20 </td> <td>1,048,536</td><td> 百万 </td> <td>1 MB</td>
  </tr>
  <tr>
    <td> 30 </td> <td>1,073,741,824</td><td> 十億 </td> <td>1 GB</td>
  </tr>
  <tr>
    <td> 32 </td> <td>4,294,967,296</td><td> - </td> <td>4 GB</td>
  </tr>
  <tr>
    <td> 40 </td> <td>1,099,511,627,776</td><td> 一兆 </td> <td>1 TB</td>
  </tr>
  </tr>
  </tr>
</table>

上記を覚えておけば、Swiftで使用される基本的な整数型とかもすぐに出てきますね。

2. **`Int8`と`UInt8`**:
   - 8ビット整数
   - `UInt8`は 0 から 2^8 - 1、すなわち 0 から 255
   - `Int8`は -2^7 から 2^7 - 1、すなわち -128 から 127

3. **`Int16`と`UInt16`**:
   - 16ビット整数
   - `UInt16`は 0 から 2^16 - 1、すなわち 0 から 65535
   - `Int16`は -2^15 から 2^15 - 1、すなわち -32768 から 32767

4. **`Int32`と`UInt32`**:
   - 32ビット整数
   - `UInt32`は 0 から 2^32 - 1、すなわち 0 から 4294967295
   - `Int32`は -2^31 から 2^31 - 1、すなわち -2147483648 から 2147483647

仮に数値として予め扱う桁数などがわかっているなら、その辺りの判断も早くなりそうですね。
データベースの正規化について

今回はデータベースについて学習したので、学習内容をアウトプットしていこうと思います。
特に重要だと思ったデータベースの正規化についてまとめられたらいいなと思います。

# データの正規化とは
まず、データの正規化について説明します。

正規化とは、データベースで使う情報を整理するための手順です。データベースでは、情報を表（テーブル）として整理して保存します。正規化をすることで、情報が整理されて分かりやすくなります。
たとえば、顧客情報を保存するデータベースを考えてみます。顧客の名前や住所、電話番号などを保存するテーブルがあります。正規化をすると、これらの情報が効率的に整理されます。
実際にこちらを正規化して説明します。

##### 基データ

| 顧客ID | 顧客名  | 住所      | 電話番号     | 注文ID | 注文日     | 商品名 | 価格 |
|--------|---------|-----------|--------------|--------|------------|--------|------|
| 1      | 山田太郎 | 東京都... | 012-3456-789 | 1      | 2024-04-01 | 商品A  | 1000 |
| 1      | 山田太郎 | 東京都... | 012-3456-789 | 2      | 2024-04-15 | 商品B  | 2000 |
| 2      | 田中花子 | 大阪府... | 098-7654-321 | 3      | 2024-04-05 | 商品C  | 1500 |

上記の図では、例えば「顧客情報」と「注文情報」が同じテーブルに混在している状況です。正規化を行わないと、顧客情報が変更された際に注文情報に影響を及ぼす可能性があります。正規化によってデータを分割することで、情報が整合的に保たれます。


なので、顧客情報」と「注文情報」を分割しました。

| 顧客ID | 顧客名  | 住所      | 電話番号     |
|--------|---------|-----------|--------------|
| 1      | 山田太郎 | 東京都... | 012-3456-789 |
| 2      | 田中花子 | 大阪府... | 098-7654-321 |

| 注文ID | 顧客ID | 注文日     | 商品名 | 価格 |
|--------|--------|------------|--------|------|
| 1      | 1      | 2024-04-01 | 商品A  | 1000 |
| 2      | 1      | 2024-04-15 | 商品B  | 2000 |
| 3      | 2      | 2024-04-05 | 商品C  | 1500 |

これによって、顧客名などが変更された場合でも、注文情報には影響を与えることは無くなりました。

現状、顧客情報と注文情報のテーブルにおいて、注文情報は顧客IDに関数従属しています。つまり、注文情報は顧客IDがわかれば一意に特定することができます。しかし、商品名と価格は注文IDにのみ関数従属しています。つまり、注文IDがわかれば一意に特定できますが、顧客IDだけでは特定できません。
そこで、以下のように、商品名と価格を注文IDに関連付ける注文明細テーブルを作成します。

| 顧客ID | 顧客名  | 住所      | 電話番号     |
|--------|---------|-----------|--------------|
| 1      | 山田太郎 | 東京都... | 012-3456-789 |
| 2      | 田中花子 | 大阪府... | 098-7654-321 |

| 注文ID | 顧客ID | 注文日     |
|--------|--------|------------|
| 1      | 1      | 2024-04-01 |
| 2      | 1      | 2024-04-15 |
| 3      | 2      | 2024-04-05 |

| 注文ID | 商品名 | 価格 |
|--------|--------|------|
| 1      | 商品A  | 1000 |
| 2      | 商品B  | 2000 |
| 3      | 商品C  | 1500 |

このようにすることで、注文情報は注文IDに関数従属し、顧客情報とは独立して管理されるようになります。データベースがより効率的に整理され、データの整合性が保たれます。

# まとめ
今回、正規化について学習内容をまとめてみました。

正規化を行うことで、データの重複や不整合を避け、データベースの管理がしやすくなります。データの整合性を保ちながら、効率的なデータ操作や検索が可能になるため、データベース設計において重要なステップとなります。

正規化によってデータベースの構造がより洗練され、データの信頼性やセキュリティも向上します。データベースを効率的に活用するためには、正規化を適切に行うことが重要だと思いました。
ホーム画面のアプリアイコンに通知数などを表示する(バッジ)【Kotlin】


ShortcutBadgerというライブラリを使用して表示させます！

https://github.com/leolin310148/ShortcutBadger

手順は公式のGithubにある通り進めていきます。


# 準備

build.gradleに

```php:build.gradle
android {

    repositories {
        mavenCentral()
    }
}

dependencies {
    implementation "me.leolin:ShortcutBadger:1.1.22@aar"
}
```
↑を追加



準備の際いろいろ手こずったのですが、詳しくは以下などを参考にしてください

https://zenn.dev/y_mimura/scraps/d75609a474d35c

https://itechblog.hatenablog.com/entry/2022/02/18/2022-02-18-172738/

https://stackoverflow.com/questions/69163511/build-was-configured-to-prefer-settings-repositories-over-project-repositories-b


# 実践


```
var badgeCount = 10
ShortcutBadger.applyCount(applicationContext, badgeCount)
```

とすることで、アプリアイコンに１０のバッジがつきます。


消したい時は、
```
ShortcutBadger.removeCount(applicationContext)
```

もしくは、
applyCountで渡す値を0にすると消える。
# 参考

https://qiita.com/ikeda_shogouki/items/4272df39ab8765ee32db

https://qiita.com/shirahon/items/431067179e1d395fee44
Scroll to Bottomを簡潔に実装する

# 結論
```swift
import SwiftUI

struct ContentView: View {
    @State private var scrollTrigger = ChangeTransmitter()
    var body: some View {
        VStack {
            MyScrollView(scrollTrigger: $scrollTrigger)
            Button("scroll to bottom") {
                scrollTrigger.trigger()
            }
        }
    }
}

struct MyScrollView: View {
    @Binding var scrollTrigger: ChangeTransmitter
    private let scrollTarget = "bottomID"

    var body: some View {
        ScrollViewReader { proxy in
            ScrollView {
                ForEach(0..<100) { index in
                    Text("\(index)")
                }
                Color.clear.frame(height: 1)
                    .id(scrollTarget)
            }
            .onChange(of: scrollTrigger) { _, _ in
                withAnimation {
                    proxy.scrollTo(scrollTarget)
                }
            }
        }
    }
}

struct ChangeTransmitter: Equatable {
    private var changeCount = 0
    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.changeCount == rhs.changeCount
    }
    mutating func trigger() {
        self.changeCount += 1
    }
}

#Preview {
    ContentView()
}
```

![RocketSim_Recording_iPhone_15_6.1_2024-05-05_19.02.31.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/2ec31316-c6ad-a32d-d5b7-5db1e69f6a79.gif)

# 経緯

<details><summary>このように書いても…</summary>

``` swift
import SwiftUI

struct ContentView: View {
    @State private var scrollTarget: Int?
    var body: some View {
        VStack {
            MyScrollView(scrollTarget: $scrollTarget)
            Button("scroll") {
                scrollTarget = 1
            }
        }
    }
}

struct MyScrollView: View {
    @Binding var scrollTarget: Int?
    var body: some View {
        ScrollViewReader { proxy in
            ScrollView {
                ForEach(0..<100) { index in
                    Text("\(index)")
                }
                Color.clear.frame(height: 1)
                    .id(1)
            }
            .onChange(of: scrollTarget) { _, newTarget in
                withAnimation {
                    proxy.scrollTo(newTarget)
                }
            }
        }
    }
}

#Preview {
    ContentView()
}
```

</details>


一度Scroll to Bottomした後、手動で位置を変え再度Scroll to Bottomを試みても、二回目以降は `onChanged{}` が呼ばれないためできない。

![RocketSim_Recording_iPhone_15_6.1_2024-05-05_18.33.26.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/ea2edd0b-8be9-b9de-ac60-d6796e02c810.gif)


以下のように書いても、変化が早すぎるためかScrollされない。

```swift
...
Button("scroll") {
    scrollTarget = nil
    scrollTarget = 1
}
...
```

また、Scroll to Bottomを実現したいだけなら`scrollTarget`は`MyScrollView`内部に隠蔽してしまいたい。
ABC062 ARC074 の問題を解いてみました

## A問題
https://atcoder.jp/contests/abc062/tasks/abc062_a

グループに番号をつけて、数字を入力するとグループの番号が返ってくる関数を作成します。
$x$ と $y$ で同じ数が返ってきた場合、同じグループに属していると言えます。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int func(int a){ //グループ番号を返す関数
  if(a == 2){
    return 3;
  }
  else if(a == 4 || a == 6 || a == 9 || a == 11){
    return 2;
  }
  else{
    return 1;
  }
}

signed main(){
  int x, y;
  cin >> x >> y;
  
  if(func(x) == func(y)){ //同じ値を返すか判定する
    cout << "Yes" << endl;
  }
  else{
    cout << "No" << endl;
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc062/tasks/abc062_b

頑張って実装しましょう。


~~~C++:回答例1
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

signed main(){
  int h, w;
  cin >> h >> w;
  
  cout << string(w + 2, '#') << endl;
  
  for(int i = 0; i < h; i++){
    string s;
    cin >> s;
    cout << "#" << s << "#" << endl;
  }
  
  cout << string(w + 2, '#') << endl;
}
~~~
~~~C++:回答例2
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

signed main(){
  int h, w;
  cin >> h >> w;
  
  vector<vector<char> > ans(h + 2, vector<char>(w + 2, '#'));
  
  for(int i = 1; i <= h; i++){
    string s;
    cin >> s;
    for(int j = 0; j < w; j++){
      ans[i][j + 1] = s[j];
    }
  }
  
  for(auto p : ans){
    for(auto q : p){
      cout << q;
    }
    cout << endl;
  }
}
~~~

## C問題
https://atcoder.jp/contests/abc062/tasks/arc074_a

まず、この問題では3つのピースをできるだけ均等に分ける必要があります。

しかし、3つではなく2つのピースに分ける場合はどうなるのかということを考えてみます。
縦のマス数・横のマス数のどちらかが偶数の場合は、完全に半分に分けることができます。

縦横どちらも奇数の場合は、$min(h, w) = S_{max} - S_{min}$ となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3602077/35d3154b-42ed-d430-6440-c91af7222488.png)


ここまで、2つのピースに分ける場合について考えてきました。
しかし、この問題では3つのピースに分ける必要があるので、ピースを $ 1:2$に分ける方法も考える必要があります。
($1:2$の$2$の方をさらに2つに分けることで、3つのピースに分けられる)

$1:2$に分けるときには、縦に分ける方法と横に分ける方法の２つがあり、制約が$2 \leq H,W \leq 10^5$ なので、これはどちら全探索できます。

~~~C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//Created by karaju.

ll func(ll h, ll w){
  ll a, b, c; //3つのピースの面積の変数
  ll ans = 1e9;
  
  for(int i = 1; i < h; i++){ //縦iマスで分ける
    a = i * w;
    ll hh = h - i; //残りのピースの縦の長さ
    
    if(w % 2 == 0 || hh % 2 == 0){ //縦横最低1つが偶数の場合
      b = c = hh * w / 2;
    }
    else{ //両方奇数の場合
      if(hh > w){ //縦のほうが長い場合
        b = (hh / 2) * w;
        c = hh * w - b;
      }
      else{ //横のほうが長い場合
        b = (w / 2) * hh;
        c = hh * w - b;
      }
    }
    
    //S_max - S_min を求める
    ans = min(ans, max({a, b, c}) - min({a, b, c}));
  }
  return ans;
}

signed main(){
  ll H, W;
  cin >> H >> W;
  
  cout << min(func(H, W), func(W, H)) << endl;
}
~~~


## D問題
https://atcoder.jp/contests/abc062/tasks/arc074_b
【セキュリティの基本】キルチェーンとは(後編)

こんにちは、昨日はサイバーキルチェーンについて紹介したので
今日はユニファイドキルチェーンについて紹介します。



ユニファイドキルチェーンとは
----
サイバーキルチェーンでカバーできなかったところを補完し包括的に管理する目的で2017年に提唱されました

サイバーキルチェーンが8つのフェーズに分けられていたのに対してユニファイドキルチェーンは3つの大フェーズと18の小フェーズに分けられています

最初の足掛かりつくり
---


・偵察
・武器化
・配送
・ソーシャルエンジニアリング
・攻撃
・永続化　
・検知回避
・遠隔操作

ネットワークを伝播させる
----

・発見
・特権昇格
・実行
・資格情報へのアクセス
・横方向展開
・アクション

目標達成のためのアクション
-----

・情報収集
・流出
・影響
・目的




どう使うか
-----
対策を練る時にそれぞれの場所でしっかりと検知できる対策は練られているのか？（多層防御）
一つの入り口に対して過剰に防御していないか（多重防御）
を確認することができます。

キルチェーンに言えることですが対策会議の時にそれぞれで共通認識を持てることも利点だと思います。


明日は
-----

明日はTry Hack Meの脆弱性マシンを使って行動をキルチェーンにあてはめながら解説していけたらと思います。
区間DP「ダルマ落とし」の自分なりにしっくりきた遷移などの理解

# はじめに
https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1611&lang=jp
区間DPの勉強をしていて、どうしてその遷移のコードになるのかというのが疑問で理解するのに時間がかかったので、自分が理解した内容を言語化します。自分用のメモをコピペしただけなので言葉がおかしい部分は許してください

https://algo-logic.info/range-dp/#
このサイトを参考にしました

# 内容
dpの定義を「dp[l][r]=[l,r)の範囲で破壊できる個数の最大値」としてその値を貰うDPで求めていく、これは[l,r)を全て破壊しなくてもいいというのが重要で一部分だけ破壊した個数が最大値になってもOK、おそらくcout<<dp[0][n]みたいにして出力したいからだと思う。[l,r)を絶対破壊するようにすると答えを求めるのがめんどくさいのかもしれない(?)


で、上の定義から、今見てる[l,r)を求めようとすると、これって二つのパターンがある

①[l+1,r-1)が全て破壊できていて、それにより今見てるlとr-1を破壊が位置関係的に可能になって[l,r)も破壊できるパターン、つまり[l,r)が全破壊できるということ。半開区間なので注意
②[l+1,r-1)の全てを破壊することはできなくて、そうなると今見てる[l]と[r-1]がだるまの状況的に破壊できないけど、DPの定義的に[l,r)で破壊できる最大値を求めるパターン。イメージ的には完全に破壊はできないけれども答えの出力を楽にするため求めている。

この二つになる。そしてこの二つの遷移を考える。
まず①は、前提として、[l+1,r-1)の間が全て破壊できて、なおかつ[l]と[r-1]が破壊できればいい。これを判定すると、まずdp[l+1][r-2]の値を見て、その値の範囲が、その区間の長さとピッタリならOK。最大値を求めているのだから、その[l+1,r-1)のDPの最大値が、ぴったり[l+1,r-1)の長さならそれってその[l+1,r-1)の区間は全て破壊できる。逆に、区間の長さとぴったり破壊できてない、つまり区間の長さより、dpに書かれた値が小さいならそれは全部破壊できていないので、①では使えない。ちなみにこの長さは、[2,5)だとすると、2,3,4となり、r-l=5-2=3でうまくいくので、
「if(r-l = dp[l][r])」となっていればよい。これを[l+1,r-1)に適応すると、「if((r-1)-(l+1)=dp[l+1][r-1])」が成り立っていればよい。あとは今見てる[l]と[r-1]が破壊できればいいので、これは入力の値を見ればいいだけで、if(abs(a[l]-a[r-1])<=1)がtrueならOKということ。

次に②は、大前提として、[l]と[r-1]は破壊できないという前提で話を進める。まぁ破壊できるのは上でやってて、DPの定義的にまだ見れてないのは、破壊できないけど値を集計したいというのが残っているという話。で、これは普通のDPみたいなのを想像すると良くて、とりあえず何をするかというと、[l,r)で、どこかに仕切りを入れる、それをiとすると、[l,i)と[i,r)に分割する。でこれって今見てる区間を二分割して、そこの最大値を貰うって話なんだけど、これを普通のDPみたいに考えると、二分割したやつって、コード的に二分割した中でさらに二分割したやつから値を貰って、その二分割したやつもさらに二分割した二つから値を貰って...みたいな話になって、なんかこうメモ化再帰みたいなイメージがいいのかわからないけどいい感じに求められる。あと重要なのは、[l]と[r-1]は破壊するつもりはないので、①みたいに、[l+1,r-1)の間で見るみたいな話じゃなくて、[l,r)のどこかを二分割するという話なのが重要。今まで書いた内容は貰うDPだけど、配るDPとしてとらえるのなら、二つの区間を合成すると思えばいい。


あとはそれを実装するだけなんだけど、実装の注意点として、初期化というか一番最初の破壊する最初から隣合ってるやつを見ないといけない。これはdp配列を作った時に初期化するか、メモ化再帰を掘って、r-l=2　のときにa[l]とa[r-1]を見てもいい、[2,4)なら、2,3で4-2=2なので正しい。
また、上の①と②で値を貰うときに、「dp[l+1][r-2]」とコードを書いてdp配列から貰おうとするのはよくない、なぜかというと、これはメモ化再帰で、f(f,0,n)として投げるわけで、ゴールからさかのぼって掘る、みたいなのがメモ化再帰の定番であって、それでいくとdp[l+1][r-2]と貰うと、掘らずに値を貰う、つまり絶対-1になってしまう。あと、[l+1,r-1)を貰うとき、dp[l+1][r-2]が正しいんだけど、dp[l+1][r-1]とr-2を間違えてしまう場合がある、でもメモ化再帰の関数にf(f,l+1,r-1)と投げれば、メモ化再帰の関数の定義的に、[l,r)の破壊できる最大の値を求めているのだから、そのままf(f,l+1,r-1)と投げればよくて、添え字ミスもないし、掘りミスもなくなるので関数に投げてもらうというのを義務付けるのが良いと思う。


# 提出
https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=9172827#1
「Pythonで学ぶ衛星データ解析基礎」で衛星データを見てみよう（２）

## 新しいHP対応になったjupyternNotebook
[（１）](https://qiita.com/motoyuki1963/items/65ab4577fea0fce3b6d8)で書いたように、衛星データのSentinelのアクセス先が変更になって、本の通りにやっても衛星データは入手できません。
GitHubに新しいサイトに対応したJupyterNotebookがあります。こちらから、新しいノートブックを入手しましょう。
https://github.com/tamanome/satelliteBook

## 必要なライブラリー
Sentinelにアクセスするためには２つのライブラリーが必要のようです。

#### openeo 
https://openeo.org/documentation/1.0/python/
https://open-eo.github.io/openeo-python-client/


#### rioxarray
https://corteva.github.io/rioxarray/stable/

２つともpipインストールで、インストールできます。

```python
pip install openeo
pip install rioxarray
```

## openeoによる接続

`openeo`でアクセスするために、`openeo.connect`のインスタンスを作ります。

```Python
import openeo
connection = openeo.connect("https://earthengine.openeo.org")
```
接続できる衛星は、これで表示することができます。
```
display(connection.list_collections())
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/bb21ba81-085f-7b26-1762-552f0c54be51.png)

では、LANDSAT8のメタデータを見てみましょう。
```Python
connection.describe_collection("LANDSAT8_L2")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/a7ecffa9-f07f-0545-f57f-05b6ac99ac46.png)


## rioxarray とは
こちらは衛星から取り出してデータを加工するために必要なライブラリーのようです。

```Python
import rioxarray
```

こちらは、データ処理の時に少しずつ理解することにします。

次にアクセスして、いろいろなところ見てみよう。
【Laravel6】最終ログイン日時をDBに保存する方法

## 問題
最終ログイン日時を取得したい

## 方法
①usersテーブルに最終ログイン日時を保存するカラム追加
②「app/Http/Controllers/Auth/LoginController.php」を編集

これだけ！

## 手順
### ①usersテーブルに最終ログイン日時を保存するカラム追加
ターミナルで↓を入力
```
php artisan make:migration add_user_table_1columns  --table=users
```

↓テーブルに追加するカラムを記入

```database/migrations/2024_05_05_165609_add_user_table_1columns.php
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // ⭐️追記↓
        $table->dateTime('last_login_at')->nullable()->after('updated_at');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('users', function (Blueprint $table) {
        // ⭐️追記↓
        $table->dropColumn('last_login_at');
    });
}
```

#### ※down()メソッド
テーブルを削除するための処理を記述する部分で、rollbackを実行したときに走る。
downメソッドは新規登録の場面では既に記述されているが、カラムの追加や削除を行うときは記述する必要がある。
記述の仕方は、upメソッドに記述したカラムに対応したdropColumnを記述するだけ。

参考
down()メソッド

https://qiita.com/yusuke___web/items/d72e9e30f353cb1c8c19

↓

```
ターミナル

php artisan migrate
```

↓

OK！

参考：カラム追加

https://qiita.com/rikako_hira/items/6a0a2b972ddbf638fefd

### ②「app/Http/Controllers/Auth/LoginController.php」を編集
```
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
// ⭐️↓追記①
use Illuminate\Http\Request;
// ⭐️↑追記

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    // ⭐️↓追記②
    protected function authenticated(Request $request, $user)
    {
        $user->last_login_at = now();
        $user->save();
    }
    // ⭐️↑追記
}
```

#### 追記①：use Illuminate\Http\Request;
```
use Illuminate\Http\Request;
```
上記↑は、以下↓のファイルを呼び出している
```
vendor/laravel/framework/src/Illuminate/Http/Request.php
```

上記を追記しないとエラーが出る
![スクリーンショット 2024-05-05 17.52.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726068/789ee1e7-9be1-7903-b252-464ad6d47a87.png)


#### 追記②：authenticated
「authenticated」はLoginController内でより「カスタマイズ」したい時に使うツールみたいなもの。
今回はこのメソッド内に、「ログインした日時を取得→DBへ保存」の動きをつけている。

authenticatedの解説

https://readouble.com/laravel/7.x/ja/authentication.html

## 参考記事
https://blog.capilano-fw.com/?p=1464#i-2

https://qiita.com/miriwo/items/abf6b6b7ec5e8983987c
【Java】CyclicBarrierによる処理同期化

Javaではマルチスレッドによる並列処理に対して同期化処理をすることができます。
同期化処理とは複数のスレッドが並行して実行されているときに処理の順番を制御することです。

同期化支援するクラスとしてCyclicBarrierというクラスが存在しています。
バリアーと呼ばれる複数スレッドが待機するポイントを処理の中で実装し、全てのスレッドがバリアーに到達すると実行されるバリアーアクションと呼ばれる処理を実行するのがCyclicBarrierの機能です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/dbba36d4-012c-91fd-561b-8d28723617ad.png)

CyclicBarrierのインスタンスを生成する際には第1引数に同期をとるスレッド数、第2引数にバリアーアクションの処理を受け取ります。


``` Sample.java
  public static void main(String[] arg) throws Exception {
    ExecutorService exe = Executors.newFixedThreadPool(5);

    CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
      System.out.println("全てのスレッドの処理が完了しました。");
    });

    for(int i = 0; i < 5; i++) {
      exe.submit(new Task(cyclicBarrier));
    }
  }
```

上記例では5つのスレッドが全てバリアに到達したら「全てのスレッドの処理が完了しました。」と出力されるバリアーアクションを引数に渡しています。


CyclicBarrierをフィールドに持ち、並列処理が実装されているTaskクラス。


``` Task.java

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Task implements Runnable {

  CyclicBarrier cyclicBarrier;

  public Task(CyclicBarrier cyclicBarrier) {
    this.cyclicBarrier = cyclicBarrier;
  }
  public void run() {
    System.out.println("実行されたスレッドのId = " + Thread.currentThread().getId());
    try {
      this.cyclicBarrier.await();
    } catch (InterruptedException | BrokenBarrierException e) {
      e.printStackTrace();
    }
  }
}
```

並列で実行される処理としては実行されているスレッドのIDを出力するだけです。

this.cyclicBarrier.await()と記載されている箇所がバリアーに当たる処理でawaitメソッドが呼ばれたスレッドは処理を中断します。全てのスレッドでawaitメソッドが呼ばれるとバリアーアクションが実行されます。


上記コードを実行すると出力される結果はこちら。

```
実行されたスレッドのId = 19
実行されたスレッドのId = 18
実行されたスレッドのId = 15
実行されたスレッドのId = 17
実行されたスレッドのId = 16
全てのスレッドの処理が完了しました。
```

5つのスレッドでIDを出力した後バリアーアクションで出力する文字列が出力されていることがわかります。
LWCで文字コードを「Shift-JIS」を指定してダウンロードする方法

## 概要
LWCでファイルを出力すると、文字コードがUTF-8となるため、Shift-JISで出力するためにはVisualforceにて「Content-Type」のcharsetにShift-JISを指定して出力するのが一般的かと思われる。
今回は、LWCでShift-JISを指定して出力するやり方について備忘を兼ねて記載する

## やること
- 外部ライブラリである`encoding.js`を静的リソースとして登録する
- LWCで静的リソースを読み込む

## 実装
1. 外部ライブラリである`encoding.js`を静的リソースとして登録する
    - [UNPKG](https://unpkg.com/browse/encoding-japanese@2.1.0/encoding.min.js)からソースコードを取得する
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/36f83bb2-cb79-ea8b-b6ae-5a8cd3516b9a.png)
    
    - 「View Row」を右クリックして「リンク先を別名で保存する」をクリックして保存する(任意の名称で良い) 
    - 保存したファイルを静的リソースに登録する。この際にSalesforceの設定画面からまたはVSCodeでデプロイする方法のどちらでも良い。（VSCodeで登録する場合は、[こちらの方の記事](https://zenn.dev/akkie1030/articles/lwc-use-npm-packages#%E9%9D%99%E7%9A%84%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E5%88%A9%E7%94%A8)が大変参考になるので、適宜参照してください）

2. LWCで静的リソースを読み込む
 - まず静的リソースの内容を読み込む
 ```javascript:lwc
 import encodejs from '@salesforce/resourceUrl/{静的リソースに登録した名称}'
import { loadScript } from 'lightning/platformResourceLoader'


export default class TestComponent extends LightningElement {
    // 静的リソースを読み込む
    connectedCallback() {
        Promise.all([loadScript(this, encodejs)])
            .then(() => {
                console.log('loaded')
            })
            .catch((error) => {
                console.log('error', error)
            })
    }
    
 ```

 - これでライブラリを使用できるようになったため、ロジックを実装する。ライブラリの詳しい使用方法は、[README](https://github.com/polygonplanet/encoding.js/blob/master/README_ja.md)を参照してください。
 ```javascript:lwc
const fileData = 'こんにちは'

 // 文字列から文字コード値の配列に変換(ASCII)
const unicodeArray = Encoding.stringToCode(fileData)

// Shift-JISのバイト配列にエンコード
const sjisArray = Encoding.convert(unicodeArray, 'SJIS', 'UNICODE')

// バイト配列からBlobオブジェクトを生成
const blobData = new Blob([new Uint8Array(sjisArray)], { type: 'text/plain' })

// ダウンロードを実行
const link = document.createElement('a')
link.download = 'hoge.txt'
link.href = window.URL.createObjectURL(blobData)
link.click()
URL.revokeObjectURL(link.href)
 ```

 ## 動作検証
 - 検証内容
   - LWC内の処理で出力されたファイルがShift-JISになっているか？
 - 動作検証の手順については、私が別で記載した記事内に記載したので、[こちら](https://qiita.com/Kyohei-takiyama/items/e6b0c620b0c44e392c19#%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D)を参考にしていただければと思います。