OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftUIベースのUIKitからDismissした時にSwiftUI側で何か処理をする

## 1. SwiftUI側
```swift:ContentView.swift
struct ContentView: View {
    
    var body: some View {
        ContentViewControllerWrapper {
            EmptyView()
        }
    }
}

struct ContentViewControllerWrapper<Content: View>: UIViewControllerRepresentable {

    private let storyboard = UIStoryboard(name: "Content", bundle: nil)

    var content: () -> Content

    func makeUIViewController(context: Context) -> ContentViewwController {
        let viewController = self.storyboard.instantiateViewController(withIdentifier: "Content") as? ContentViewController
        return viewController ?? ContentViewController()
    }

    func updateUIViewController(_ uiviewController: ContentViewController, context: Context) {
    }
}

```

## 2. UIViewController側
表示して3秒後に閉じる
```swift:ContentViewController.swift

final class SetupViewController: UIViewController {

    // MARK: - LifeCycle

    override func viewDidLoad() {
        super.viewDidLoad()
        DispatchQueue.main.asyncAfter(deadline: .now() + 3.0, execute: {
            self.dismiss(animated: true)
        })
    }
}
```

## 3.Delegateの実装
Delegate実装側
```diff_Swift
+ protocol ContentViewDelegate {
+     func dismiss()
+ }

struct ContentView: View {

+   var delegate: ContentViewDelegate?

    var body: some View {
        ContentViewControllerWrapper {
            EmptyView()
        }
+       .onDisappear { self.delegate?.dismiss() }
    }
}
```

Delegate呼び出し側
~~SwiftUIアンチなのでUIKitベースで遷移~~
```swift:MainView.swift
var contentView = ContentView()
contentView.delegate = self
// 以下処理は引用を参照
self.viewController?.present(style: .formSheet, transitionStyle: .coverVertical) { contentView }

// MARK: - ContentViewDelegate

extension MainView: ContentViewDelegate {

    func dismiss() {
        // 戻った時にやりたい処理
    }
}
```

[How to present crossDissolve view in swiftUI?](https://stackoverflow.com/questions/60391281/how-to-present-crossdissolve-view-in-swiftui)
Amazon Linuxコンテナーでmountコマンドを使いたい

dockerhubに存在するamazonlinuxイメージを指定して起動したAmazon Linuxコンテナーは非常に小さく、mountコマンドさえ入っていない。
Redhat系OSでmountコマンドが含まれるパッケージ名を調べたので、メモとしてここに記録して置く。

```bash
# yum install bind
```

上記の通り、yumでbindパッケージをインストールすれば、mountコマンドが使用可能となる。

### 経緯

昨年、一般公開された[Mountpoint for Amazon S3](https://github.com/awslabs/mountpoint-s3/)をamazonlinuxコンテナー上で試すことが出来たのは良かったが、マウントしたS3バケットをアンマウントするにはumountコマンドが必要となり、amazonlinuxコンテナーにはumountコマンドが入っておらず、少し困ってしまった。
ちなみに、amazonlinuxイメージの現時点の最新（latest）は2023.3.20240131.0となるが、このバージョンはyumが正常動作しなかった（「curl: (6) getaddrinfo() thread failed to start」と言うエラーが発生した）ので、amazonlinux:2のDockerイメージを使用した。
市民開発者を育てる上で気を付けないといけないことPart3

# 1,はじめに
今回でpart3となりました。

https://qiita.com/thxUVER2012/items/7705d45029ae89b9bc7b

https://qiita.com/thxUVER2012/items/f553a9d6ed085534e417

大人に対して教えること、子供に対して教えることは違うなと感じています。
大人になると過去の経験をベースで物事を考えていて、その経験を理解した上で育てることが難しいです。
また学生時代は類推的な考え方を用いていたのに、大人になりその考え方を使わなくなったり、新たな考え方を感得したりすることができない人もいます。




# 2,市民開発者のモチベのケア
:::note alert
開発したいけど、講師から難しいと言われると嫌になる。
:::

市民開発者が開発したいものを持ってきた時に、難しいロジックになることはあります。
この時に多くの市民開発者は「私にはできない」などネガティブになります。

:::note info
誰にだってこの感覚はあるので、寄り添いながらほらこれでできるじゃん！と言うこと！
:::

私は教員をしていたので、この場面には何度も出会いました。
正直言うと私も某国立大学の入試問題を教える時には一度解いて、何だこの問題難しいなとできないわーとなることもあります。
そのため、この嫌になる気持ちは理解することができます！
仕事でもこの仕事難しい嫌だなと思ったら市民開発者も同じ気持ちになっています。
では本題に戻って、**モチベを上げるためにはこの難しいものは知ってしまえば、簡単だよって伝えることが大事です**。

:::note warn
難しいと思う理由はいくつかあります。
1,解決の手法を知らない。
2,抽象的だから。
:::

これらを解決することが大事です。

# 3,アクティビティを統合的に見ることができるか？
:::note alert
アクティビティは多いため、全てを覚えることは難しいです。
なので私は新しいアクティビティが出て時には、間違えてもいいから相違点を常に考えて、覚えることを節約しています。
この感覚を育てることも大事です。
:::

では繰り返しといったらいくつ思い浮かびますか？
調べてみるとたくさんありますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/d0e80cd8-27d2-8547-c1c5-a0616091eb83.png)
データテーブルの各行はよく使用すると思いますので、これをベースに統合していきます。
例えば、下記の2つは繰り返しというワードが同じですが、フォルダー内の各ファイルと同じことはありますか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/c04b63db-230a-203a-c0c0-28640a206906.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/d5581f1f-36c2-15bd-90a5-8b2d7855ea07.png)

:::note warn
直感を働かせてみて同じ要素を考えてみましょう。
1,CuurentRow、CuurentFile(緑枠)
2,繰り返したいアクティビティを配置する位置(赤枠)
これらが同じだろうと思ったら、その直感を頼りにしてわからないところ(サブフォルダを含むなど)を調べて、アクティビティを実行してみましょう。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/433e5ebe-185b-b41e-5b9f-76334de1253e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/3a893d49-e69f-10f6-1f82-25e0c1fe7fef.png)

# 3,市民開発者自身で保守運用しやすいようにコードレビューをする

:::note alert
市民開発者自身で保守運用できるようにロボットを制御すること。
:::

:::note info
(1)テスト時に使用しているアクティビティにはマークを付ける。
(2)市民開発者が説明できないVb.Netは使わせない。
(3)開発したロボットを誰かに引き継ぐことも考えて注釈などを残す。
:::

### (1)テスト時に使用しているアクティビティにはマークを付ける。
下記のように社内ルール化することでコードレビューするときにマークで検索すればいいのでレビューする側の負担も減ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/930a018d-6082-e893-4f5c-799627755f3c.png)

### (2)市民開発者が説明できないVb.Netは使わせない。
これを許してしまうと、誰も保守運用ができないです。
下記の記事の **「3.(3)Configファイル(設定ファイル)の備考やアクティビティに注釈を書く。」** を参考にしてください。

https://qiita.com/thxUVER2012/items/11923133a781afce35be

### (3)開発したロボットを誰かに引き継ぐことも考えて注釈などを残す。
これを行うか行わないかで誰でも保守運用するできるようにすること。
下記の記事の **「3,UiPathの引継ぎ資料とは？」** を参考にしてください。

https://qiita.com/thxUVER2012/items/11923133a781afce35be

# 4,おわりに
教えることは難しいなと感じながら業務をしています。
またUiPathでうまくいかないところを市民開発者と解決したときは嬉しいですね。
今、市民開発者のスケジュール管理などをしているため、リーダーの大変さも痛感しています。
ようつべ体験記16

ついにチャンネル登録者数100を突破しました。
![スクリーンショット 2024-02-17 9.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/6c12b897-f0f0-961f-bf96-e9f29a8ef55e.png)

6ヶ月半かかりました。
正直3ヶ月ぐらいで達成できるかなという気持ちもあったので、結構大変でした。
![Frame 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/5d78876b-764a-6913-3171-ad1d9b3c3ef7.png)

2024/01/11 以降、インプレッション数が 3000回/日 以上維持されています。
それにともなって、視聴回数も 200回/日 以上を維持できるようになりました。
チャンネル登録者数も 1人/日 を越えて、一気に 100 に到達できました。

その日まではリピーター数が 20人/日 程度でしたが、50人/日ぐらいになりました。
![スクリーンショット 2024-02-18 20.49.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/f9002df7-185f-d39d-8f8b-ddc4c75760ae.png)

この日に投稿した動画は、約1ヶ月で 470回 見ていただけました。
比較的良い方ですが、特別すごいものが投稿できた訳ではないです。
![スクリーンショット 2024-02-18 20.52.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/aa79d91f-0a97-c8a2-4e42-c2d55fb57fdf.png)

過去の動画の蓄積でチャンネルが伸びたようです。
- まず山吹色の動画がグイッと伸びて
- 他のもちょろちょろ伸びつつ
- 黄緑色の動画がググっと伸びた
![スクリーンショット 2024-02-18 16.58.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/fd2018e4-445f-81d8-b90c-023c419fc9bf.png)

収益化まであと 900人。
今のペースだとあと 900日...。
![スクリーンショット 2024-02-18 20.42.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/a441908c-21d7-ee37-4cc1-aab84ae9aa55.png)
【Git】LF will be replaced by CRLF the next time Git touches it 警告の解消方法

# 背景
新しく使い始めたPCのgit、vscodeの環境を構築し開発環境を整えていた。
vscodeのターミナルで`git add .`を実行した際に下記の警告が表示された。


# 警告
`git add .`を実行時に下記のwarningがターミナルに表示。
```
warning: in the working copy of 'src/App.tsx', LF will be replaced by CRLF the next time Git touches it
```

# 原因
以下、DeepLで日本語に翻訳してみた内容です。
```
警告：作業コピーの'src/App.tsx'では、次にGitが触ったときにLFがCRLFに置き換えられます。
```

Gitが改行コードをLFからCRLFに変更しようとしいてるみたい。


# 解決策
次のコマンドを実行し、`git add`コマンド実行時に警告が表示されなくなった事を確認できた。
```
git config --global core.autoCRLF false
```
【CSS】子要素の数に応じてスタイルを適用する方法

## 特定の数の場合にのみ適用

以下のように記述すると子要素が指定した数の場合にのみスタイルを適用できます。

```css
ul:has(> :nth-child(N):last-child) li {  }
```

子要素が２つの場合にのみスタイルを適用するには以下のように記述します。

```css
ul:has(> :nth-child(2):last-child) li {  }
```

## 特定の数以上の場合にのみ適用

以下のように`:has()`を使用することで指定した数以上子要素が存在する場合にのみスタイルを適用できます。

```css
ul:has(> :nth-child(N)) li { }
```

2つ以上ある場合にスタイルを適用するには以下のようにします。

```css
ul:has(> :nth-child(2)) li { }
```

https://developer.mozilla.org/ja/docs/Web/CSS/:has

https://developer.mozilla.org/ja/docs/Web/CSS/Child_combinator

https://developer.mozilla.org/ja/docs/Web/CSS/:nth-child
ショートカットでアプリ起動 [Mac向け]

# はじめに
Macに標準でインストールされているショートカットアプリで、アプリを起動するようにしたら、少しだけ効率が良くなったので紹介します。

# 設定方法
### 1. ショートカットアプリを開く
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/3cc28558-e170-8eeb-ae77-72f32d6143fb.png" width="100px" height="100px" />

### 2. 以下のような画面が表示されるので、右上の`+`ボタンを押す 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/b03a3610-4cb2-26aa-e667-4db713c9237a.png)

### 3.「アプリを開く」アクションを左のスペースにドラッグ＆ドロップする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/b6776e51-df20-807f-797e-f8a8395d0ed4.png)

### 4.「アプリを開く」アクションの`アプリ`をクリックすると検索バーが表示されるので、今回使用したいアプリを検索する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/cdd53f5c-bf00-9845-6fe3-f310f3f617fa.png)

### 5. 右上の`i`アイコンをクリックし、キーボードショートカットを追加をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/f14226c5-d6c9-2a35-5a80-c835889de30b.png)

### 6. 右側の入力欄にて、登録するショートカットキーを入力
今回はWordに関連して、`Ctrl + W`と入力しました。他のショートカットキーと被りが無いか確認して追加するようにしましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/046c3f8e-6916-1ce2-8139-b36e127c7da3.png)

### 7. ショートカット名を入力して終了
画面上部に名前を入力することが出来ます。完了ボタンは無いのでバツボタンでウインドウを閉じると、一覧画面に今回作成したショートカットが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3085757/38b743c5-955a-18cd-e7f3-52e645db5bc6.png)

# 最後に
ショートカットはこれ以外の使い方をしたことがないので、他の使い方も調べてみたいと思いました。
他の使い方などは以下の公式サイトなどを参考にすると良いと思います。
最後まで読んでいただきありがとうございました。

https://support.apple.com/ja-jp/guide/shortcuts-mac/apdf22b0444c/mac
Laravelのディレクティブまとめ

# はじめに

Laravelを勉強中の初心者です。この記事では、Laravelでよく使われるディレクティブについてまとめていきます。
参照：https://readouble.com/laravel/9.x/ja/blade.html

# 1.レイアウトに関連するディレクティブ
## 1-1.ビューの継承（@&#xFFF0;extends）
他のビューを継承する。
```
@extends('layouts.app')
```

## 1-2.ビューの挿入（@&#xFFF0;include）
他のビューファイルを読み込んで表示する。
```
@include('sidebar')
```

## 1-3.セクションの挿入（@&#xFFF0;section,@&#xFFF0;yield）
@&#xFFF0;sectionでセクションの内容を定義し、@&#xFFF0;yieldで内容を表示する。
```
@section('content')
   <p>コンテンツ</p>
@endsection
```
```
@yield('content')
```

# 2.処理に関連するディレクティブ
## 2-1.条件分岐（@&#xFFF0;if）
```
@if (Auth::check())
    <p>ログインしています。</p>
@else
    <p>ログインしていません。</p>
@endif
```

## 2-2.ループ（@&#xFFF0;for,@&#xFFF0;foreach,@&#xFFF0;while）
1から5までの数字を出力する。
```
@for ($i = 1; $i <= 5; $i++)
    <li>{{ $i }}</li>
@endfor
```
```
@php
$numbers = [1, 2, 3, 4, 5];
@endphp

@foreach ($numbers as $number)
    <p>{{ $number }}</p>
@endforeach
```
```
@php
$i = 1;
@endphp

@while ($i <= 5)
    <p>{{ $i }}</p>
    @php
    $i++;
    @endphp
@endwhile
```

## 2-3.CSRF対策（@&#xFFF0;csrf）
フォームでセキュリティを保護するためにCSRFトークンを生成する（下記）。
```
@csrf
```

## 2-4.HTMLメソッド（@&#xFFF0;method）
PUT, PATCH, DELETEなどのHTTPメソッドを直接使えないので、@&#xFFF0;methodを使う。
```
<form action="/hoge" method="POST">
    @method('PUT')
    @csrf
</form>
```
Pythonでのツール作成時に困ったこと⑤


これまでに続き、Pythonのツール作成時に実際に起きた困ったことをまとめました。

①メモリ不足
1000万件を超えるデータを処理していたところ以下のエラーが発生しました。
　memoryerorr
調べてみるとPCのメモリ不足が原因でエラーが発生したようです。
複数dateframeを作成していたためメモリ不足になったようです。
dateframeの数を減らすことでメモリ不足が解決し正常に処理をできるようになりました。


② dateframeの項目を結合で、エラーとなっても表示されない

dateframeをmergeで結合させ出力するツールを作成したところ、処理が終了し出力されても結合されていないという事象がありました。

原因を調べたところ、onで指定したキーのデータ型が異なっており結合できておらず
結合されずにその後の処理が進んでいました。
エラーメッセージも表示されないため問題ないと思っていましたが
実際のデータをテストをして気づくことができました。
キーのデータ型を揃える処理をして正しく処理できるようになりました。
SQLBuilderの仕様を考える　DELETE仕様検討編

# 目的
GolangのSQLBuilerを作ってみたくて、仕様を考える。
今回はDELETE文の仕様を考える。また、TRUNCATEも併せて考える。

# 目指す形
ここではusersというTableに対応したUserというTableモデル構造体がある場合とする。
宣言としては、
```
CREATE TABLE users (
  id int,
  name varchar(10)
)

CREATE TABLE tokens (
  id int,
  user_id int REFERENCES users.id,
  token varchar(10)
)
```
を想定する

## DELETE

パッケージ名は仮でpkとして

```go
pk.DELETE(pk.Table("users"))

// DELETE FROM users
```

とすることを考えている。

WHERE句の利用は

```go
pk.DELETE(pk.Table("users")).WHERE(pk.Eq("users.id"), 1)

// DELETE FROM users WHERE users.id = 1
```
を考えており、WHERE句としてはSELECT文と同じ

## TRUNCATE
パッケージ名は仮でpkとして

```go
pk.TRUNCATE(pk.Table("users"))

// TRUNCATE TABLE users
```
SQLBuilderの仕様を考える　UPDATE仕様検討編

# 目的
GolangのSQLBuilerを作ってみたくて、仕様を考える。
今回はUPDATE文の仕様を考える。

# 目指す形
ここではusersというTableに対応したUserというTableモデル構造体がある場合とする。
宣言としては、
```
CREATE TABLE users (
  id int,
  name varchar(10)
)

CREATE TABLE tokens (
  id int,
  user_id int REFERENCES users.id,
  token varchar(10)
)
```
を想定する

## Update

パッケージ名は仮でpkとして

```go
pk.Update(pk.Table("users")).Set("name", "test")

// UPDATE users set name = 'test'
```

とすることを考えている。

複数カラムに関しては

```go
pk.Update(pk.Table("users")).Set("id", 2).Set("name", "test")

// UPDATE users set id = 2, name = 'test'
```

また、以下のような連想配列も許可する

```go
um := map[string]interface{}
um["id"] = 2
um["name"] = "test"

pk.Update(pk.Table("users")).SetMap(um)

// UPDATE users set id = 2, name = 'test'
```

## Where句の利用
利用としては以下を想定

```go
pk.Update(pk.Table("users")).Set("name", "test").Where(pk.Eq("id", 1))

// UPDATE users set name = 'test' where id = 1
```

また、以下のようにも利用できるようにする。

```go
user := pk.Table("users")

pk.Update(users).Set(user.Col("name"), "test").Where(pk.Eq(user.Col("id"), 1))

// UPDATE users set users.name = 'test' where users.id = 1
```

AS句が利用されても適応される想定はSELECT文の時と同じ

```go
user := pk.Table("users").AS("u")

pk.Update(users).Set(user.Col("name"), "test").Where(pk.Eq(user.Col("id"), 1))

// UPDATE users AS u set u.name = 'test' where u.id = 1
```
【Emmet】爆速でCSSを書く方法！(AWS Cloud9)

こんばんは！
今日はEmmetのHTMLの記事に続き、CSSのEmmetを使用したコーディングを紹介します！
タイトルにある通り、環境はAWS Cloud9で特にインストールするものはありません。

## 基本の操作
 Emmetの略語(この後紹介します)を入力後、`Ctrl+Alt+E`で展開できます。といってもイメージ湧かないかもしれないので、早速紹介に入りたいと思います！

### CSS略語一覧(チートシートより抜粋)

| CSS略語 | Ctrl+Alt+Eで展開後の表示 |
|:-:|:-:|
| m  | margin: ;  |
|  m:a |  margin: auto; |
|  mt |  margin-top: ; |
|  p | padding: ;  |
|  pt | padding-top: ;  |
|  w100 | width: 100px;  |
|  wa |  width: auto; |
|  ha | height: auto;  |
|  maw | max-width: ;  |
|  miw | min-width: ;  |
| fw |font-weight: ;  |
|fw:b|font-weight: bold;|
| fw:n  | font-weight: normal;  |
| fz  | font-size: ;  |
|  ta:c | text-align: center;  |
| lh  |  line-height: ; |
| jc  | justify-content: ;  |
|jc:c|justify-content: center;|
| fx  |  flex: ; |
|  fxw | flex-wrap: ;  |
|  c | color: #000;  |
|  op | opacity: ;  |
|  cur |  cursor: pointer; |
|z|z-index: ;|
|pos|position: relative;|
|pos:a|position: absolute;|
|fl|float: left;|

例外ももちろんありますが、tはtop、rはright、bはbottom、aはautoなど、なんとなくパターンが決まっているので、大体頭文字を入れてみると変換できそうです。
チートシートはこちらです↓　情報量がかなり多いので、よく使うものだけ覚えるのが効率よさそうです。

https://docs.emmet.io/cheat-sheet/

### 最後に
PFは決められた期間で1人で作業することになるので、いかにHTMLとCSSを早く記述できるかが大事になってくると思うので、あと半月で覚えて使えるようになりたいです:muscle:
初めてのハッカソン参加

# 初めてのハッカソンに参加した話
## 自己紹介
- 大学2年生
- プログラミング歴2年
- 主な主要言語 javascript

　今回人生で初めてハッカソンに参加しました。
　参加した理由はずっとハッカソンに参加すると経験にもなるため参加したいと思っていて広島に住んでいる私は中国地方とかで開催されたら行こうくらいの気持ちでいました。
　個人で学習しているとやはり情報が手に入れられる速度には限りがあります．そのため実際につよつよエンジニアの同年代の学生を目にしたらモチベも上がるし情報も得られて最高なんじゃないかと思って大学で所属している技術系サークルの皆を誘って参加してみることにしました。
 ## 参加したハッカソンについて
 https://hackz-community.doorkeeper.jp/events/167551
 
 今回のハッカソンは**株式会社ハックツ**主催のハックツハッカソン~ツマジロカップ~です。
 参加人数は20名でチームは7チームでのハッカソンでした。
 メンターとしてProgateとHelpfeelの方がいらしていたのですが、自分にはとても贅沢な体験でした。

 ## 開発したアプリについて
 
https://topaz.dev/projects/fa8515c746d1c536fbc1

今回開発したアプリの名前は「忍者の知恵広場」です。
アプリについてはtopazのページを見ていただけるとわかりやすいと思います！

## 感想

今回ハッカソンに参加してみて本当に良かったです。
ハッカソンは泊まりこみで開発を行いますがこれまでの人生で一番プログラムに向き合った日かもしれません笑一日中プログラムを見ていました笑
ハッカソンには何といっても自分の力を成長させる場、技術の高い人たちに出会える場だと思います。ほかのグループの発表を見ていましたが、全く勝てる気がしませんでした。どのグループの発表者も自分たちが２日間かけて開発したものを楽しそうに話していました。でもそれで萎えてしまうというよりは自分をもっと成長させてこのグループたちに勝てるようなアイデア、技術を身に付けるべきだと感じました。
あと今回のハッカソンで目標ができました！
それは何かのハッカソンで最優秀賞を取るまではハッカソンに参加し続けるという目標です！
最優秀賞を取るにはかなりの技術量が必要です。最優秀賞に値するくらいの技術をこれからの学習で身に付けていきたい！！！！
3月にはもう一度ほかのハッカソンに参加します！それまでに少しでも実力上げます！
padでのExcel保存でのバグ

Power Automate DesktopでExcelファイルを保存しようとしたところ、ファイル形式がExcelでなくなるという事象がありました。

保存モードは「名前を付けてドキュメントを保存」を選択します。
使用したアクションは「Excelの保存」です。
保存モード「名前を付けてドキュメントを保存」を選択します。
ドキュメント形式「Excelブック」もしくは「既存の拡張子」を選択します。

ファイル名が以下のようにドットが入っていると最初のドットの後を拡張子と認識されないようで
保存はされても、Excelで開くことができなくなります。
　●●.▲▲.xlsx

保存するファイル名から以下のようにドットを除くと保存したファイルもExcelで開けるようになります。
　●●▲▲.xlsx
PowerPoint でプレゼン資料を作る時に考えていること

# はじめに
ごきげんよう、百合宮 桜です。
今回は、PowerPoint で資料を作る時に考えていることを言語化してみようと思います。
基本的に登壇資料ばかり作っているので、読み物スタイルの時のこだわりはあまりないです。
登壇資料ってどうやって作るねん！って時に参考にしていただければ幸いです。

# その資料、読み物ですか？ 登壇資料ですか？
まず、自分が作るものをターゲットはどういう状態で目にするのか、を考えます。
具体的には

- 読み物スタイル：自習の様に、説明者不在で、ひとりで読む
- 登壇資料スタイル：講義の様に、説明する人がいて、話を聞く

です。

## 読み物スタイル

読み物であるならば、私が直接説明することは叶いません。
それゆえに補足説明なしでも理解できるように、スライドを作り上げる必要があります。
おおよそ企業が出している調査まとめや霞が関パワポのような形式がこちらにあたると考えます。
IT 界隈では色々な意味で話題になった、こちらの銀行さんのレポートが個人的に好きな読み物スタイルです。
文字が多いですが、情報が整理されているため、分かりやすいです。
さらに言えば注目する部分は色が変えてあるので目を引きますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/7807ec9f-bb23-efc9-2d1d-a253c64270dd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/867d7308-51c8-d2fd-eefd-4965732ebfea.png)
出典
https://www.mizuhobank.co.jp/corporate/bizinfo/industry/sangyou/m1073.html

## 登壇資料スタイル

登壇資料ならば、私が直接説明できます。
その為、ターゲットは

- 資料を見ること
- 説明者の話を聞くこと

の2つを同時に行うことを求められます。
さて、人間はマルチタスクが苦手な生き物です。
実際に登壇を聞いてみると分かりますが、資料にある大量の文章を読みながら、登壇者の話を聞くというのはできるようでいて、できません。その資料が初見ならば、なおさらできません。
ゆえに資料を作成する場合、ターゲットがマルチタスクを行えるように資料の情報量を調整する必要があります。


# ターゲットが求めていることは何ですか？

仕事で作る資料ならば、必ずターゲットからのオーダーがあるはずです。
私の場合、作成する資料の多くは Microsoft 365 や Power Platform の使い方などが多いです。しかし、使い方もベストプラクティスも Microsoft Learn に書いてある！
つまり、わざわざ我々に依頼しなくても Microsoft さんの資料読めば無料で習得できるのですよねｗ
そんなに恵まれた状況の中、我々に依頼してくるというのは何か理由があるはずです。
- 依頼理由ってなんだろうか？
- Microsoft Learn と一緒じゃんと思われない為にできることは何か？

この2つに対して、自分なりの解が持てれば、資料は大体完成しています。
とはいえ、それができていれば、そもそもあなたはこのページを見ていないはずです。
なのでもう少し具体的に言語化していきます。

ターゲットがMicrosoft Learn に書いてある事項のプレゼンテーションを望む理由は、大体以下のパターンがおおです。

- できるだけ Microsoft Learn を読みたくない
- Microsoft Learn を読んでも理解できなかった
- 短い時間で効率的に理解したい
- そもそも Microsoft Learn のどこを読めば良いのか見当がつかない（迷子）

ということは、最短で理解できるように 

- Microsoft Learn を平易な言葉に置き換える
- 専門知識が必要な部分は補足説明を加える
- 画像が英語で理解しにくい場合は、日本語のスクリーンショットを撮り直す
- 上記をすべて行った上で理解しやすい順番に並び替える

がターゲットを満足させる為のミッションです。
これらを行うためには Microsoft Learn の熟読はもちろんですが、ターゲットを気遣いながら資料を構成する力が不可欠です。以降では構成を考えるうえで、どんなことに気を使っているのかを説明していきます。


# その資料、ひと目で理解できますか？
ひと目で理解できるということは

- 説明者の話を聞きながらでも、文章がひと目で読める量
- ターゲットが理解できる一般的な言葉

であるか、ということです。

多少の専門用語が入ってしまうのは、説明の都合上、仕方ない部分もあるでしょう。
でも文章量を意識的に減らすことは可能なはず。
私は基本的に

- 見出し文は28ポイントで1行
- その下の要約文は18ポイントで2行

に抑えるようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/0a2a102c-906f-8fee-0e38-621a18ad56e4.png)

これでは情報量が足りないのでは？と思うかもしれません。
そこは登壇なので、直接口頭で説明します。
あえて文字数を減らすことで、ターゲットには説明者の話に集中してもらいやすい環境を作っています。

# その資料、規則性はありますか？
人間は、規則性のある方が読みやすい生き物です。

- 画像の位置
- 見出し文と要約文の頭位置
- フォントの大きさ

などは、すべてのスライドで統一されていますか？


# その資料、導線は適切ですか？
1枚のスライドの中に画像や文章が多すぎて、説明者がどこの話をしているのか、分からない……という現象は本当によくあります。
画像は多くても2枚までに絞り込み、どうしてもそれ以上載せたい場合はアニメーションをつけるなど、ターゲットが画像に注目できるような仕組みを作りましょう。

# その登壇、リハーサルはしてますか？
リハーサルをすると、説明しきれていないと思う部分が出てきます。
その理由としては

- 自分の中で理解しきれていない
- スライド上の情報量が膨大で説明しにくい

のどちらかです。
スライド上の情報量が多すぎる場合はターゲットも受け取り切れません。
その時点でリハーサルを中止し、スライドの構成を見直してみてください。

# 終わりに

皆さん、いかがでしたか？
参考にして、楽しいスライド / 登壇ライフをお過ごしください(*'▽')
ごきげんよう✨
WSL 上の VSCode で Paste Image 拡張機能が正常動作しないので手動回避した話

## WSL 上の Paste Image は残念な感じ

- Windows 上のブラウザから画像をクリップボードにコピーしても、コピーされるのは Windows のクリップボード
- Paste Image 拡張機能を使っても、WSL 上のクリップボードは空っぽなので、画像貼り付けに失敗

## 何とかしようとした人々

### WSL にクリップボード内容を画像で保存しようとした実装

- [WSL上からWindowsのクリップボードに保存されている画像をpng保存する](https://qiita.com/yugo-yamamoto/items/1538344af52a0bdf4e75)
- 一応使えるが、画像名を入力しなければならないのは面倒

### Windows のクリップボード内容を WSL にコピーする実装

- [vscodeのpaste image extensionをWSL2で使う（非推奨）](https://metaproxy.co/pasteImageWithWSL2/)
- 使えなくはないが、途中のコマンドが多くてお手軽ではない
- ただし、コマンドが一発になれば悪くない

## 省力設計で何とかした結果

- Windows のクリップボード内容を WSL にコピーできることが判明した
- ので、これを Python スクリプトで作成すれば OK
- だが、面倒なので、最近新しくなった Gemini 大先生に作成してもらう

### 入力したプロンプト

```text
Windows システムのクリップボードの内容を WSL 上のクリップボードにコピーする方法はありますか？
あるならば、これを実行するPythonスクリプトを作成してください。この際、Pythonスクリプトは、次の要件を満たすものとします。

- PythonスクリプトはWSL上で実行するものとします。
- Pythonスクリプトは引数を必要とせず、自動的にWindowsシステムのクリップボード内容を取得します。
- 一行目には `#!/usr/bin/env python3` を記載して下さい。
```

### 帰ってきた結果

- `clip.exe`を使用してクリップボード内容を取得、`xclip`を使用して WSL のクリップボードに内容をセットするコードが生成された

```python
#!/usr/bin/env python3
import subprocess

# Windows システムのクリップボードの内容を取得
def get_windows_clipboard():
    p = subprocess.Popen(['clip.exe', '-noparse'], stdout=subprocess.PIPE)
    output, err = p.communicate()
    if err:
        raise Exception('Failed to get Windows clipboard content')
    return output.decode('utf-8').strip()

# WSL 上のクリップボードに内容を設定
def set_wsl_clipboard(text):
    p = subprocess.Popen(['xclip', '-selection', 'clipboard', '-in'], stdin=subprocess.PIPE)
    p.communicate(input=text.encode('utf-8'))

# 実行
windows_clipboard_content = get_windows_clipboard()
set_wsl_clipboard(windows_clipboard_content)

print('Windows システムのクリップボードの内容を WSL 上のクリップボードにコピーしました。')
```

### 実行結果

- 適当にパスの通った場所へスクリプトを置き、使いやすい名前（`ccp`）を付けて、実行権限を付与
- 実行してみると、文字コードバグが出ているものの正常に実行される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569749/65c367e8-5f84-661a-cf19-64587938c0f6.png)

- スクリプト実行後に`Paste Image`拡張機能を使用してみると・・・正常に張り付けが完了した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569749/078ef6f6-3647-487f-3066-2a146b787450.png)

### ついでに Chat GPT で作成した場合

- 内容は似ているものの、エラー処理の無い、PowerShell を使用したコードが生成された
- 実行してみると、文字化けのアウトプットも無く、正常に動作した

```python
#!/usr/bin/env python3
import subprocess

# Windows のクリップボード内容を取得
get_clipboard_cmd = ['powershell.exe', '-command', 'Get-Clipboard']
clipboard_content = subprocess.check_output(get_clipboard_cmd, text=True)

# WSL のクリップボードに内容をコピー
with subprocess.Popen(['xclip', '-selection', 'c'], stdin=subprocess.PIPE) as proc:
    proc.communicate(input=clipboard_content.encode())
```

## まとめ

- 小さな便利コード程度の作成であれば、その基礎的な知識も含め、もはや人間が調べつつ作成する必要はなくなりつつあることを実感しました
- Gemini も Chat GPT も至極便利
@slotと@componentの使い方

# はじめに
bladeファイルの中で、何回も使用するパーツがあったりしますよね。その際に@componentを使用すると、コードがすっきりする、メンテナンスが楽になるので、使用方法を備忘録として残します。

# @componentの使い方
````php:sample.blade.php
@component(components.test)

// 表示させたい内容

@endcomponent

````

上記の場合、例えば「View」フォルダの「Components」フォルダ内の「test.blade.php」が表示されます。

# @slotの使い方
上記の例で挙げた「test.blade.php」で変数を使用したいとします。@component内で変数を使用したい場合は、@slotを用います。

````php:sample.blade.php
@component(components.test)

@slot('name', $name)

@endcomponent
````

````php:test.blade.php
<div>
    <h1>コンポーネント</h1>
    <p class="name">{{$name}}</p>
</div>
````
@slotで定義した変数名の前に$をつけて記載すると、変数を表示させることができます。
[SwiftUI] Preview作成時のポイント(APIを介さずデータをセットする)

SwiftUIのpreview機能について、活用方法について簡単にまとめていきたいと思います。

### APIに依存しない
ViewとModel形式で構成されているケース(VM)を例に考えていきます。この場合、基本的にView側で表示する内容はModel側で保持しているPublish変数を展開していくことになると思います。そして、そのPublish変数の中身というのはAPIを通して取得してきたデータを詰めていることと思います。
previewを実装する場合、このPublish変数にAPIを通して詰めるのではなく、自分でpreview用のダミーデータを詰める関数を用意してやることがポイントになります。APIを通して詰めるようにしてしまうと、変更時に毎回APIを叩くことになり、その分待ち時間が発生し、previewの特徴である手早くViewの修正・確認ができるメリットが薄れてしまうことになるからです。最低限この点は意識するようにしましょう。

### ダミーデータ生成の関数を用意
まずは上記で話したようにPublish変数にダミーデータを詰める関数を用意しましょう。この関数自体をどこに置くかは議論の余地がありますが、今回は分かりやすくする為Model内で書くこととします。

```swift
class ProductModel: ObservableObject {
  @Published var products: [Product] = [] // 商品一覧
  // 商品の型
  struct Product: Identifiable {
    var id: UUID = .init()
    var productId: Int
    var productName: String
    var productImgUrl: String
  }
  extension ProductModel {
    // preview用の商品データ作成
    func createProductDummyData() {
      for _ in 1 ... 8 {
        self.products.append(Product(productId: 1,
                                    productName: "ダミー",
                                    productImgUrl: "https://dummy"))
      }
    }
  }
}
```
これでダミーデータを作成する関数を用意することができました。ちなみにextension内に記載しているのは実ロジックとの区別をつける為です。この点も議論の余地がありますが、今回はこのやり方で進めていきます。

### モデルを外部注入できる作りにする
実装のイメージとしてはpreviewの中でモデルインスタンスを作成し、上記で作成したダミー関数を呼んで予めPublish変数に値を詰めた状態でView側に渡すという形が望ましいです。これを実現するにはモデルインスタンスをView側に外部注入できる作りになっていないといけないのですが、下記のような実装になっていると困難です。
```swift
# 修正前
struct ProductView: View {
@StateObject var productModel: ProductModel
init() {
    _productViewModel = StateObject(wrappedValue: ProductModel())
  }
}
```
上記の作りではinit時の処理の中で、Modelインスタンスを生成してしまっている為、外部注入ができません。下記のように修正してみましょう。

```swift
# 修正後
struct ProductView: View {
@StateObject var productModel: ProductModel
init(productModel: ProductModel? = nil) {
   _productModel = StateObject(wrappedValue: productModel ?? ProductModel())
  }
}
```
上記の修正により、外部から渡って来なければそのまま新規にインスタンスを作成し、渡ってくればそれをそのまま使用することができるようになりました。これで諸所の準備が完了しましたので、実際にPreview側に書いてみましょう。

```swift
# 最終実装
struct ProductView: View {
@StateObject var productModel: ProductModel
init(productModel: ProductModel? = nil) {
   _productModel = StateObject(wrappedValue: productModel ?? ProductModel())
  }
}

#Preview("商品一覧") {
  let productModel = ProductModel()
  productModel.createProductDummyData()
  ProductView(productModel: productModel)
}
```
これでAPIを介さずに、Preview機能を使用できるようになりました。簡単ですね

## 終わりに
以上がPreview機能を実装する際のポイントでした。どんどんpreview機能を活用して、開発効率を上げていけると良いですね。
Jetpack ComposeのCanvasでメーターのような可変する円を作る

# drawCircle()
```
    Canvas(
        modifier = Modifier.size(250.dp),
        onDraw = {
            drawCircle(Color.Green)
        }
    )
```
![スクリーンショット 2024-02-18 21.38.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/2138b393-544f-2223-e67c-3c6cb8184c14.png)

可変でない場合の円の場合は**drawCircle()** または、**drawOval()** 使用すればいいのですが、メーターのように中を可変させたい場合は、**drawArc()** を使用します。

次は上のdrawCircle()を背景としてdrawArc()を使ってみましょう.

# drawArc()

```
    Column(
        Modifier.size(225.dp)
    ) {
        Canvas(
            modifier = Modifier.size(225.dp),
            onDraw = {
            
                drawCircle(Color.Green)
                
                drawArc(
                    color = Color.Yellow,
                    startAngle = -90f,
                    sweepAngle = 90f,
                    useCenter = true,
                )
            }
        )
    }
```
![スクリーンショット 2024-02-18 21.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/04700429-9688-db09-d62f-a66a09b9f8ef.png)
**startAngle**と**sweepAngle**を指定することで
上の画像のようのできます。

例えば、何かのメーターのように使いたいなら、表示したい情報を取得した時や数秒置きなどにと**sweepAngle**を調節すればいいと思います。
sweepAngleはstartAngleの位置からの角度になります。

**startAngle**は 0が時計の３時の方向ななっているので、メーターのスタート位置を円の上部にしたい場合、270f　もしくは-90fを指定します。
（私が触ったプロジェクトでは270fだとうまく表示されない時があった。謎。）

# 注意
**useCenter**をfalseにすると、以下のようになるので必ずtrueにしておきましょう。

![スクリーンショット 2024-02-18 21.59.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/c5f0862e-1044-ecc9-6134-1ad0c0e56ea8.png)


Canvas()の外枠を Column()（たぶん何でもいい）などで囲って範囲を指定しないと
![スクリーンショット 2024-02-18 22.33.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/84306e23-f395-3db3-127c-111c9d5c46e8.png)
こんな感じで表示できる範囲いっぱいに表示されてしまう。

# 参考
https://developer.android.com/jetpack/compose/graphics/draw/overview?hl=ja
XSS対策でエスケープ処理をする

## はじめに
xssはサイバー攻撃の一種で、悪意のあるユーザが投稿型webページに悪意のあるjavascriptを投稿し、アクセスしたユーザにそのコードを実行させ個人情報を盗むなど攻撃します。

## 対策方法
エスケープ処理を使って対策していきます。エスケープ処理とは投稿されたjavascriptのコードをただの文字列に置き換える方法です。

## 対策方法
今回、対策するにはエスケープ処理をします。javascriptのコードをただの文字列にします。
第一引数はエスケープ処理したい文字列、第二引数はどのように置き換えるか、第三引数は変換時の文字コードになります。
```php
$string = '<script>alert(1);</script>';
$string = htmlspecialchars($string, ENT_QUOTES, 'utf-8');
```
```
<script>alert(1);</script>
```
javascriptが実行されずに文字列として出力されました。

## 終わりに
サイバー攻撃は後を絶ちません。また、サイバー攻撃の被害などに遭うと顧客情報の流出など、顧客の方に不安を抱かせたり、信用をなくします。対策自体簡単なのでしっかり対策していきたいです。
マルチモジュールでの依存関係の記述をいい感じにする

# マルチモジュール

マルチモジュールは、どんどん肥大化するプロジェクトにおいて効率性を維持するためにおすすめの方法です。アプリケーションを独立したモジュールに分割することで

- ビルドの高速化
- よいアーキテクチャを強制できる

というメリットがあります。

一方で、モジュールの数が増えると、各モジュールでそれぞれ依存関係を管理するのは大変です。バージョンカタログを導入することによって、マルチモジュールでの依存関係を簡単に管理できるようになります。

## バージョンカタログ

バージョンカタログは依存ライブラリとプラグインのバージョンを一元管理するためのGradleの機能です。

### バージョンカタログファイルを作成

ルートの`gradle`フォルダに`libs.versions.toml`ファイルを作成します。Gradleはデフォルトでこのファイル名を読み込むので、ファイルを作成するだけで大丈夫です。

```libs.version.toml
[versions]

[libraries]

[plugins]
```

### ライブラリの場合

バージョンカタログファイルの`versions`と`libraries`に追加します。ライブラリに追加する名前はケバブケース(`androidx-core-ktx`など)にします。こうすると`build.gradle.kts`ではdotに置き換えた形で参照できます(`libs.androidx.core.ktx`)

#### 変更前

```build.gradle.kts
dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
}
```

#### 変更後

```libs.versions.toml
[versions]
core-ktx = "1.12.0"

[libraries]
androidx-core-ktx = { group = "androidx.core", name="core-ktx", version.ref = "core-ktx" }

```
```build.gradle.kts
dependencies {
    implementation(libs.androidx.core.ktx)
}
```

### プラグインの場合

#### 変更前

```Top-level build.gradle.kts
plugins {
    id("com.android.application") version "8.2.2" apply false
}
```
```Module-level build.gradle.kts
plugins {
    id("com.android.application")
}
```

#### 変更後

```libs.versions.toml
[versions]
androidGradlePlugin = "8.2.2"

[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
```
```Top-level build.gradle.kts
plugins {
    alias(libs.plugins.android.application) apply false
}
```
```Module-level build.gradle.kts
plugins {
    alias(libs.plugins.android.application)
}
```

### バージョンの設定

バージョン名をそのまま使うパターンも同様です。

#### 変更前

```build.gradke.kts
android {
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.7"
    }
}
```

#### 変更後

```libs.versions.toml
[versions]
androidxComposeCompiler = "1.5.7"
```
```build.gradle.kts
android {
    composeOptions {
        kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get().toString()
    }
}
```

## プロジェクト間の依存

Gradle 7.0で試験的に導入されたTYPESAFE_PROJECT_ACCESSORS機能を使うと、プロジェクトの依存もバージョンカタログと同じように、文字列ではなく型安全に参照できます。

#### 変更前

```build.gralde.kts
dependencies {
    implementation(project(":core:data"))
}
```

#### 変更後

```settings.gradle
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
```
```build.gralde.kts
dependencies {
    implementation(projects.core.data)
}
```

# 参考

https://developer.android.com/build/migrate-to-catalogs

https://docs.gradle.org/current/userguide/platforms.html

https://docs.gradle.org/7.0/release-notes.html
【TypeScript】 wideningについて

## 概要
TypeScriptのtype assersionやsatisfiesについて調べていましたが、まずは`widening`について理解していないと説明ができないと感じ、まずは`widening`についてまとめてみました。

## 型推論について
`widening`の前に、型推論についても少し触れておきます。
型推論とは、型注釈（アノテーション）しなくても、`TypeScript`が文脈を読んで型を推論してくれる機能です。

そして、今まで勘違いしていたんですが、
```typescript
const foo = "foo";
```
のような、const宣言だと`string`型で型推論されているかと思っていましたが実は、
```typescript
const foo: "foo" = "foo";
```
のように"foo"という文字列リテラル型として型推論されています。要するに`"foo"`というプリミティブ値(オブジェクトではなく、メソッドを持たない値)しか代入できません。

逆に、再代入可能な`let`宣言だと、
```typescript
let bar = "bar";
//  ↓
let bar: string = "bar";
```
のようにstring型に推論されるため、
```typescript
let bar = "bar";
bar = "barbar"
```
と再代入しても、同じstring型なので、怒られません。

数値リテラル型や真偽値リテラル型についても同様で、
```typescript
const num = 100;
//  100型という数値リテラル型に推論される

const shin = true;
// true型（真偽値リテラル型）に推論される
```

### 配列やオブジェクトの場合
配列やオブジェクトの場合は注意が必要で、const宣言とlet宣言が同じ型推論となります。const宣言だからと安心していたら大変なことになります。

```typescript
let letArr = [0, 1, 2, 3]; // : number[]型で推論される

const cstArr = [0, 1, 2, 3]; // : number[]型で推論される

cstArr[0] = 100; // cstArrはconst宣言なのに、再代入しても怒られない
```

```typescript
let letObj = { a: "hoge", b: 777 }; // : { a: string; b: number; }型で推論される

let cstObj = { a: "hoge", b: 777 }; // : { a: string; b: number; }型で推論される

cstObj.a = "fuga"; // cstObjはconst宣言なのに、再代入しても怒られない
```
配列、オブジェクトの場合は、配列の各要素または、各プロパティ値は、プリミティブ型とはならないので、注意が必要です。

## 型がwideningするとは

```typescript
const foo = "foo"; // foo: "foo"型
let bar = foo; //bar: string型
bar = "bar"; //怒られない
```
このケースのように、型が`:"foo"`→`:string`のように緩くなることをwideningすると言います。

## 参考
https://typescriptbook.jp/reference/values-types-variables/literal-types

https://developer.mozilla.org/ja/docs/Glossary/Primitive

https://zenn.dev/estra/articles/typescript-widening

https://qiita.com/yamashin0616/items/f6f2405dba4570638228

https://zenn.dev/imokeeeenpi/articles/f6a41563187407
【Pythonでゼロから作るデータ構造】スタック(Stack)編

## ご挨拶
はじめまして^^

hrm441といいます、よろしくお願いします

今回は基礎的なデータ構造であるスタックを、Pythonのクラスを使って自作してみました

タイトルの "ゼロから" というのは、「listオブジェクトにある'append'や'pop'などの内部メソッドを使わず、それらも自分の手で実装してみよう」という意味を込めてのものです！

大学の課題やコーディングテスト対策として参考になれば幸いです♪(~~自分はこれが初めてのインターン面接で出されて爆死しました~~)


#### コード
```python
#スタックの実装
#スタックとはLIFO(Last in First out)のデータ構造
#作成日 2024/2/17
class Stack:
    INITIAL_SIZE = 10 #配列の初期サイズ
    
    def __init__(self):
        self.items = [None] * Stack.INITIAL_SIZE  #初期化
        self.size = 0 #現在のスタックのサイズ
        
    def is_empty(self):
        return self.size == 0
    
    def push(self, item):
        if self.size < len(self.items):
            self.items[self.size] = item
            self.size += 1
        else:
            raise OverflowError("Stack overflow")
    
    def pop(self):
        if self.is_empty():
            raise IndexError("pop from empty stack")
        else:
            self.size -= 1
            item = self.items[self.size]
            self.items[self.size] = None #削除された要素はNoneで置き換え
            return item
    
    def top(self):
        if self.is_empty():
            raise IndexError("top from empty stack")
        else:
            return self.items[self.size - 1]
        
    def get_size(self):
        return self.size
    
    
            
```
async関数が返す値はPromiseになるんじゃないの…？

# はじめに
どうもこんにちは！僕は現在1ヵ月本気の技術力向上を目指している現役高校生1年生です！今回はjavascriptでの非同期処理の書き方をちゃんと理解していなかったのでまとめます。

# 問題
以下のようなコードがあったとします。

<font color="grey">※処理の内容としては非同期処理と関係なさそうなものですが、あくまでも書き方のサンプルコードなのでご了承ください。</font>
```javascript
//userはオブジェクトとします
const getName = async (user) => {
    return user.name;
}

const checkName = (user) => {
    const name = await getName(user);
}
```

ここで次の疑問が浮いてきました。
> async関数ってPromiseオブジェクトを返すはずなのになんで変数(name)に格納できてるの？？

# 結論
> <font color="red">**awaitをつけるとPromiseの中身が返却される**</font>

awaitをつけると、**Promise.then((res) => { … }**) を省略した形で書けるということだそうです。

# 終わりに
awaitについては見ての通り、時間のかかる処理(外部からデータを取得するとか)を「待ってくれる」という意味でしか捉えていなかったので調べておいてよかったです。非同期処理のところはまだ理解があいまいなのでまた躓いたときに戻ってこようと思いました。

# 参考
https://qiita.com/niusounds/items/37c1f9b021b62194e077

# About Me
- X(Twitter)
https://twitter.com/shunii_hack
UniversalDetectorが固まる問題に直面した方へ

# chardetを使ってみた
えーと、テキストのencodingをいい感じに判定してくれるPythonモジュール、chardetを使ってみました。で、色々地雷が埋まったファイル群を処理させていただいたのですが、改行のないギガバイト級ファイルで見事固まってくれました。わざわざ嵌めたので、解決に苦労はしませんでしたが、不意打ちで嵌まった人がいたらちょっと悩むかもしれないので、解決法を書いておきます。特にWEBで言及している人が見つからなかったので！

よくあるコードは、こんなんです。

```python
import chardet

def readfile(path):
    detector = chardet.UniversalDetector()
    with open(path, 'rb') as f:
        detector.feed(line)  # ここから帰ってこない
        if detector.done:
            break
    detector.close()
    
    # 得られたエンコーディング情報を使ってファイルをオープンし直すが、
    # それでもエラーになる場合は、エラー文字を読み飛ばして無理やり読む
    with open(path, encoding=detector.result['encoding'], errors='ignore') as f:
        s = f.read()

    return s
```

chardetを紹介しているウェブ上のサンプルソースはどれもこれも大体同じだから、詳しい説明はそちらに譲ります。

で、前述のファイルを食わせると、「ここから帰ってこない」というコメントをつけた行で固まる。これは痛い。

# 例えばこんな風に直す
きれいじゃないけど、要は小出しにUniversalDetectorにfeedしてあげるとよろし、と言う話。ただ、2バイト文字が境界に来たりして、本当はちょっと危険なのだが、その辺は、64kbyteもあれば判定つくよね、ってことで細かいことは気にしていない。境界に来るようなケースを試したけど、特にヤバい現象は起きない模様なので、それはそれで良しとします。あと、後半で読み込み直したときにファイルがでかすぎる問題は、今回の本題じゃないので皆さんそれぞれご自分のタスクに合った解決をしてくれれば幸甚。

```python
import chardet

def readfile(path):
    detector = chardet.UniversalDetector()
    with open(path, 'rb') as f:
        for line in f:
            # 馬鹿みたいに改行のないテキストを読んでしまったとき、UniversalDetectorが固まるのを防ぐ
            if len(line) > 65536:
                for i in range(0, len(line), 65536):
                    detector.feed(line[i: i + 65536])
                    if detector.done:
                        break
                else:  # いつ見てもキモい多重ループ脱出イディオム
                    continue
                break
            else:
                detector.feed(line)
                if detector.done:
                    break
    detector.close()
    
    # 得られたエンコーディング情報を使ってファイルをオープンし直すが、
    # それでもエラーになる場合は、エラー文字を読み飛ばして無理やり読む
    with open(path, encoding=detector.result['encoding'], errors='ignore') as f:
        s = f.read()
    return s
```

あと、大量のテキストを処理する場合は、途中で落ちると大変残念な気持ちになります。地味にerrors='ignore'も大事かも。
LeetCode 1642. Furthest Building You Can Reachの解き方メモ

https://leetcode.com/problems/furthest-building-you-can-reach/description/

LeetCode 1642. Furthest Building You Can Reachの解き方メモです。2024/02/18現在、難易度はMediumですが、解くのにかなりてこずったので、自分用に解説を残しておきたいと思います。

- N個のビルを左から右に移動していく
- 次に移動するビルが現在のビルより低い場合は、そのまま移動できる
- 次に移動するビルが現在のビルより高い場合は、考慮が必要
    - はしごを持っている場合は、はしごを利用する
    - はしごがなくなったら、れんがを利用する。このとき使うれんがの数をできるだけ節約したい
        - はしごでのぼってきた箇所、および、これからのぼろうとしている箇所のうち、もっとも高低差が小さいところをれんがでのぼったことにする
        - れんがも足りなくなったら処理終了

「はしごでのぼってきた箇所、および、これからのぼろうとしている箇所のうち、もっとも高低差が小さいところ」←これについては優先度付きキューを使って管理すればよいです。

```rust
use std::{cmp::Reverse, collections::BinaryHeap};

impl Solution {
    pub fn furthest_building(heights: Vec<i32>, bricks: i32, ladders: i32) -> i32 {
        let mut bricks = bricks;
        let mut ladders = ladders;

        let mut heap = BinaryHeap::new();
        let mut i = 0;
        while i < heights.len() {
            if i == heights.len() - 1 {
                break;
            }

            if heights[i] >= heights[i + 1] {
                i += 1;
                continue;
            }

            heap.push(Reverse(heights[i + 1] - heights[i]));

            if ladders > 0 {
                ladders -= 1;
                i += 1;
            } else {
                match heap.pop() {
                    Some(Reverse(min)) => {
                        if min <= bricks {
                            bricks -= min;
                            i += 1;
                        } else {
                            break;
                        }
                    }
                    None => break,
                }
            }
        }

        i as i32
    }
}
```
【Swift】if文とswitch文の使い分けについて

こんにちは！
今回は第１回目と２回目に投稿したif文とswitch文で、２つの制御構文の使い分けについてアウトプットしていこうと思います。
どちらも条件によって処理を分けることをしてくれますが、どのような場面で使い分ければいいか？いまいち理解しておりませんでしたので、今回はこちらを纏めていきまーす！

まず復習がてら２つの制御構文の説明を簡単に記載します。
## if文
- switch文を用いて網羅的に条件分岐を記述できます
- 条件はどのデータ型（String型、Int型、Double型、enum型）でも指定が可能です

```swift:title.swift
var score: Int = 80

if score == 　100 {
  print("大変良くできました。")
} else if  score >= 80 {
  print("良くできました。")
} else if  score >= 60 {
  print("もう少し")
} else { 
  print("頑張りましょう")
}
```

## switch文
- switch文を用いて網羅的に条件分岐を記述できます
- 条件はどのデータ型（String型、Int型、Double型、enum型）でも指定が可能です

```swift:title.swift
var score: Int = 80

switch score {
case 100:
    print("大変良くできました。")
case 80...99:
    print("良くできました。")
case 60...79:
    print("もう少し")
default:
    print("頑張りましょう")
}
```

## 使い分けについて
それでは本題である使い分けについて説明していきます。
ケースバイケースでどちらの利用するか選択しますが、今日はしっかり使い分けの観点を押さえておきます。

下記のサンプルコードを加えて少し詳しく説明します。
```swift:title.swift
// if文
let fruit = "りんご"

if fruit == "りんご" {
    print("りんごを食べる")
} else if fruit == "みかん" {
    print("みかんを食べる")
} else if fruit == "ぶどう" {
    print("ぶどうを食べる")
} else {
    print("その他の果物を食べる")
}


// switch文
let fruit = "りんご"

switch fruit {
case "りんご":
    print("りんごを食べる")
case "みかん":
    print("みかんを食べる")
case "ぶどう":
    print("ぶどうを食べる")
default:
    print("その他の果物を食べる")
}


```
この例では、果物の状態を確認して、対応する行動（「りんごを食べる」など）を表示しています。

### その１：網羅的に条件分岐を行う必要があるとき。
この場合は、switch文を利用することを推奨してます。
何故なら`if else`を使用した場合、どの条件にも一致せず処理がスルーされてしまうことがあります。
その反面　`switch`であれば最後に`default`を設定する必要があるため、網羅的に条件分岐を行うことができます。

- if-else文では、果物が「りんご」か「みかん」か「ぶどう」かを順番に確認しています。もし新しい果物が出てきた場合、何もしないで処理が進んでしまうことがあります
対照的に、switch文では果物の状態を一度確認し、それに対応する行動を見つけるのが簡単です。そして、defaultの部分には「その他の果物を食べる」という処理が書かれているので、新しい果物が追加されても対応がしやすいです。


### その2：評価条件が多い場合
3つ以上の可能性がある状態について同じ値を確認したい場合は、可読性の観点から`if else`よりも`switch`を推奨してます。
異なる条件を多く記載するより、その値を繰り返しチェックしていることが明確になるからです。

- if-else文では、果物が「りんご」か「みかん」か「ぶどう」かを順番に確認しています。対照的に、switch文では果物の状態を一度確認し、それに対応する行動を見つけるのが簡単です。どちらも同じ結果を得られますが、switch文の方がコードを短く、可読性が高くできます

## まとめ
今回はif文とswitch文の使い分けについて説明させて頂きました。
ケースバイケースで使い分けられるように理解しておく必要はありますね。

それではまた！
(c++)array の初期化について補足

下記の記事に関する補足ですが、量が多いので別記事にします。
泥縄的学習法...

https://qiita.com/yumimatoba14/items/42da6439a6ba247efd74

# array の初期化でも2重 {} が必要だった(?)
[cpprefjp](https://cpprefjp.github.io/lang/cpp14/brace_elision_in_array_temporary_initialization.html)によると C++11 では2重の {} が必要だったようです。

```C++
std::array<double,3> x1 = {1, 2, 3};   // こう書けるのは C++14 から
std::array<double,3> x2 = {{1, 2, 3}}  // C++11 ではこう
```

と思ってこの項目を作ったのですが、よく調べてみるとちょっと違いそう。
「C++11時点では2重 {} が必要だった場合がある」が正しそうです。

多分こういうこと。

```C++
std::array<double,3> x1 = {1, 2, 3};   // C++11 でもOK
std::array<double,3> x2 = {{1, 2, 3}}  // C++11 でももちろんOK
std::array<double,3> x3{1, 2, 3};      // こう書けるのは C++14 から
std::array<double,3> x4{{1, 2, 3}};    // C++11 でももちろんOK
```

[Issue #1270](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270) というのが参照されていますが、この1270 は「= がある時だけ省略できる」のがバグと言っているのだと思われます。

まあ今さらどちらでもいいけど...

参考リンク:

* [initializer-listによるaggregate初期化の制約緩和](https://yohhoy.hatenadiary.jp/entry/20131116/p1)
* [vector/arrayとUniform initialization+Initializer list](https://yohhoy.hatenadiary.jp/entry/20120724/p1)
* [C++ Standard Core Language Defect Reports and Accepted Issues, Revision 113](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270)

# (C の) 構造体の初期化における未指定要素の値
以下のページより引用:

https://cpplover.blogspot.com/2010/09/aggregate.html

> そして、初期化リストによって初期化する際に、配列や構造体のメンバーに、対応する初期化リストの値がない場合、staticストレージと同じように初期化される。staticストレージは、必ずゼロで初期化されることが保証されている。したがって、上記のコードは、「a[0]を0で初期化し、残りの要素をstaticストレージと同じ方法で初期化せよ」という意味である。

この記事によると私の「C 言語では末尾に 0 を書くと後続の未指定要素は 0 になる」という認識が間違い。単に「未指定要素が 0 になる」。 で C++ の集成体の初期化でも同じ動作が継承されていると。

ちなみに上記記事では「初期化リスト」と「std::initializer_list」を別物として使い分けて記事が書かれているようです。この記事における「初期化リスト」の詳細を知りたい...

# そもそも array を直接座標値型として使えばいいんじゃね?
soreja さんより 以下のようにすればいいのでは、とのコメントをいただきました。 この件について所感を。
```C++
namespace cpp14 {
using Vector3d = std::array<double, 3>;

template<class T, size_t N>
std::array<T, N>& operator+=(std::array<T, N>& l, const std::array<T, N>& r);
}
```

## array を直接座標値として使う方針について
元記事を書きながら「array を直接利用すればいいんじゃね」という発想は得ていましたが、どちらかというと否定的でした。

気になる点
* 演算子の自前オーバーロードを std 名前空間に定義するのに抵抗があった。(クラスと同じ名前空間(std)に入れるべしと思い込んでいました。)
* メンバ関数の追加ができない。(C# なら拡張メソッドとかで対応する部分。)
    * 長さ/ノルム の計算をするメンバ関数とか。 2項演算系のものはグローバル関数として実装するのでもよいと思いますが、そうじゃないものもあるかなと。
* array のデータメンバが public。

一方で、 C 言語で double の配列を座標値として使う方針がありなら、それ以上には array を座標値として使うのはありだと思います。 メンバ関数の形で実装しなくてはならないのは仮想関数位で、座標値クラスで仮想関数はほぼ不要でしょう。 あとはメンバ関数とグローバル関数の違いは見た目・趣味の問題でしかないと思います。 (アクセス制限の話はなくはない。また趣味の問題と言いつつ、今さら関数ライブラリを使いたいかと言われれば抵抗も感じますが。)

今回は自分の中で「既に存在する VectorN に `{1, 2, 3}` みたいな表記を受け入れさせたい」という暗黙の前提があったので状況が異なりますが、例えば計算用には 2D版, 3D版を個別に実装し、n 次元が欲しい時だけ array を使うという方針はありだと思います。
計算用と array 版でインタフェースが揃わないという指摘は以下の観点で大きな問題にはならないでしょう。
* そもそも n 次元版共通のインタフェースはそれほど多くない。 むしろベクトルの外積のように次元毎にインタフェースが違うものもある。
    * 「N次元版が欲しい」の中身は、実際上割と array で事足りる。
* クラスの違いは Traits クラスで吸収することも可能。

## std::array の演算子はオーバーロードしないかも
他方 soreja さんのサンプルにある演算子のオーバーロードですが、あれは私はやらないか、局所的なコードとするかなあと思います。 マナーとしては、演算子のオーバーロードはクラスと同じ名前空間で定義されるべきと思っているので。
Kindle Cloud Readerでランダムにページを表示しながら対応するテキストを読み上げていくスクリプト

<h3>Kindle Cloud Readerでランダムにページを表示しながら対応するテキストを読み上げていくスクリプト</h3>
<a hr="https://qiita.com/shizuoka_miyako_19911118/items/d4a3515778cf2aed8725">前に作ったPowershellスクリプト</a>
(https://qiita.com/shizuoka_miyako_19911118/items/d4a3515778cf2aed8725)
を修正して
Kindle Cloud Readerでランダムにページを表示しながら対応するテキストを読み上げていくスクリプトを作成しました

githubURL:https://github.com/NanjoMiyako2/kindleCloudReaderRandomPagesYomiage

<hr>
PGM

```powershell

#SendKeysを使うため、System.Windows.Forms名前空間読込
Add-Type -AssemblyName System.Windows.Forms

#テキスト読み上げ用
Add-Type -AssemblyName System.Speech

$ps_speak = New-Object System.Speech.Synthesis.SpeechSynthesizer
$ps_speak.SelectVoice("Microsoft Haruka Desktop")


#読み出し時間(秒)
$ReadSecond = 60
#何ページ分繰り返すか
$CountLength = 30
#読み出す本の最大ページ数
$BookPages = 16


#音声読み上げ用ファイルを読み込み
$arr = Get-Content "C:\hogehoge\aiueo-Text1.txt"
#echo $arr


# .NET Frameworkの宣言
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

# Windows APIの宣言
$signature=@'
[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@
$SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru

echo "ランダム読み出し開始"
#この間にトップ画面をkindleにする
Start-Sleep -s 60
echo "Start"


for($i=0; $i -lt $CountLength; $i++){

# 変数設定
#---A---
$x = 1888
$y = 140


# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);


Start-Sleep -s 5

# 変数設定
#---B---
$x = 1821
$y = 276

# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

Start-Sleep -s 2
$page = Get-Random -Maximum $BookPages -Minimum 1
[System.Windows.Forms.SendKeys]::SendWait($page)
Start-Sleep -s 2

# 変数設定
#---C---
$x = 1064
$y = 632

# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

Start-Sleep -s 10

$ps_speak.Speak($arr[($page-1)])


Start-Sleep -s $ReadSecond


}





```
AWS App syncとAWS Kinesis data streamsの違いについての備忘録

## 違いの簡単な結論
1. AWS AppSyncはクライアントとバックエンドの間でのリアルタイムなデータ同期
2. Amazon Kinesis Data Streamsは大規模なリアルタイムデータの収集、処理、分析に使用

### AWS App Syncについて
個々のデータ項目のリアルタイムな同期に適してる

### AWS Kinesis Data Streams
大量のイベントやデータのストリーム全体を処理するのに適している

#### AWS AppSync使用例
あなたのウェブアプリは、ユーザーが新しいメッセージを投稿したときにリアルタイムでデータを更新する必要があります。ここでAWS AppSyncを使用すると、クライアント（ウェブブラウザやモバイルアプリ）とバックエンドのデータソース（たとえばDynamoDB）間でリアルタイムデータ同期が可能になります。ユーザーがメッセージを投稿すると、即座に他のユーザーの画面にそのメッセージが表示されます。

#### AWS Kinesis Data Streams
あなたのウェブアプリは、数百万人のユーザーが同時にリアルタイムでイベントを発生させ、それらのイベントを分析してリアルタイムなレコメンデーションやアラートを生成したいとします。この場合、Amazon Kinesis Data Streamsを使用することで、数十万/秒のイベントを受信し、ストリーム処理を行い、そのデータをさまざまな処理パイプラインに渡すことができます。例えば、特定の行動パターンに基づいてユーザーにリアルタイムな推奨を提供するなどのアクションを実行できます。


ここは違うよ〜ここはこの方が？等々ございましたらご指摘いただけますと幸いです。
ここまでお読みいただきありがとうございました。
円や点を描く【道具としての OpenCV 画像認識】

# 本記事でできること
画像に円や中実円を描画し、画面に表示します。
![draw_circle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/93ffcb8f-aef6-e421-2bbb-fd22abb91f69.png)


# 想定シーン
## ロボットをビジュアルフィードバック制御する
カメラを使ったロボットアームの制御方法を、ビジュアルフィードバック制御といいます。ここでは、ビジュアルフィードバック制御を使った自動化システムを開発する際に必要となる画像認識プログラムをまとめています。

## 円や点を描く
ビジュアルフィードバック制御における画像処理をする際に、認識したターゲット物体やロボットの注視領域を表示するために円を描きたい、という場合があります。対象舞台上の目標点と、ロボットの制御点を表示して、制御が収束していることを描画するなどの用途でも使用します。本記事では、円（circle）と中実円（中が詰まった円）を描画するプログラムを掲載します。

# 実行環境
- OS：Ubuntu 22.04 LTS
- 言語：C++
- クルーボ：v5.1.0

## クルーボについて
ロボットアプリケーション開発には、株式会社チトセロボティクスのロボット制御ソフトウェア「クルーボ」を使用します。本記事のプログラムは、クルーボがインストールされた制御コンピュータ上で動作します。

- クルーボの製品サイト：https://chitose-robotics.com/product

## プログラム抜粋
```c++
cv::Mat draw_circle(
        const cv::Mat image, const cv::Point center, const float radius, const cv::Scalar color, const int thickness) {
    cv::Mat drawed_image = image.clone();
    cv::circle(drawed_image, center, static_cast<int>(radius), color, thickness, CV_MSA);
    return drawed_image;
}

cv::Mat draw_dot(const cv::Mat image, const cv::Point center, const float radius, const cv::Scalar color) {
    cv::Mat drawed_image = image.clone();
    const int thickness = -1;
    cv::circle(drawed_image, center, static_cast<int>(radius), color, thickness, CV_MSA);
    return drawed_image;
}
```

## 全体プログラム
```c++
#include <iostream>
#include <opencv2/opencv.hpp>

cv::Mat draw_circle(
        const cv::Mat image, const cv::Point center, const float radius, const cv::Scalar color, const int thickness) {
    cv::Mat drawed_image = image.clone();
    cv::circle(drawed_image, center, static_cast<int>(radius), color, thickness, CV_MSA);
    return drawed_image;
}

cv::Mat draw_dot(const cv::Mat image, const cv::Point center, const float radius, const cv::Scalar color) {
    cv::Mat drawed_image = image.clone();
    const int thickness = -1;
    cv::circle(drawed_image, center, static_cast<int>(radius), color, thickness, CV_MSA);
    return drawed_image;
}

int main(void) {
    const cv::Size image_size(1280, 960);
    const cv::Mat black_image = cv::Mat::zeros(image_size.height, image_size.width, CV_8UC3);

    cv::Mat drawed_image = black_image.clone();

    const cv::Point circle_center(200, 300);
    const float circle_radius = 70.f;
    drawed_image = draw_circle(drawed_image, circle_center, circle_radius, cv::Scalar(0, 0, 255), 5);

    const cv::Point dot_center(700, 500);
    const float dot_radius = 40.f;
    drawed_image = draw_dot(drawed_image, dot_center, dot_radius, cv::Scalar(255, 0, 0));

    cv::imshow("drawed_image", drawed_image);
    cv::waitKey(0);
}
```


## おわりに
人手作業をロボットアームで自動化するために、カメラを使ったロボット制御＝ビジュアルフィードバック制御が大切です。
ロボット制御用の画像認識でも中身のひとつひとつはシンプルなので、要素に分解して解説していきたいと思います。