OmniAICreator/Qiita-1.07M huggingface dataset:
クラスインスタンスに読み込んだ設定を反映するメモ

# きっかけ
- PyYAMLで読み込んだ設定をクラスインスタンスに反映させる処理を汎化したかった

# YAMLファイル（test.yaml）の記述

```
name: 'Iceberg'
type: 'double-handed sword'
element: 'ice'
range: 1
```

# ソースコード
- 下記の実行ファイルと前述のYAMLファイルは同じディレクトリにある前提

```
import yaml

class TestClass():
    def __init__(self):
        self.name = ''
        self.type = ''
        self.element = ''

    def load_config(self, config_path):
        with open(config_path, encoding='utf-8') as file:
            loaded_data = yaml.safe_load(file)
        
        for class_loop in vars(self):
            if class_loop in loaded_data.keys():
                setattr(self, class_loop, loaded_data[class_loop])

tc = TestClass()
tc.load_config('test.yaml')

print(vars(tc))
```

# 結果

```
{'name': 'Iceberg', 'type': 'double-handed sword', 'element': 'ice'}
```

# 参考
- https://stackoverflow.com/questions/69658171/how-to-change-the-values-of-instance-attributes-in-a-loop
セキュリティ相談を受けたときに引用したい記事集(WIP)

# セキュリティ相談を受けたときに引用したい記事・ニュース集・事例集

## これは何？

セキュリティ相談受けた際、過去のインシデントや事例などを引用して、「その対策必要なの？」というい疑問への説得力を持たせたりすることがあります。
が、その場で思い出せることは稀です。よく引用できていますが、「どっかにあった気がするんだけどな〜」と思って思い出せないことが7割くらいな気がします。

そんなことがないように、ここにまとめていきます。
いつかまとめたいと思っていたんですが、すぐ思い出せないので永遠に先延ばしにしていたので、未完成のまま公開します。
少しずつ思い出す度に増やします。
BetterThanNothingの精神です。
参考: https://www.youtube.com/watch?v=bnfPUrJQh1I

## 事例集

### 各種プロダクトのセキュリティガイドラインなど

- メルカリさんのgithub actionsに関するセキュリティガイドライン
  - https://engineering.mercari.com/blog/entry/20230609-github-actions-guideline/

### リスト型攻撃

- メールアドレス登録状況が閲覧できることが攻撃に悪用された事例
  - https://scan.netsecurity.ne.jp/article/2018/06/12/41039.html


### Githubに機微な情報を置かない方が良い

- 認証情報
 - https://corp.classi.jp/news/2416/
- 個人情報
 - https://about.mercari.com/press/news/articles/20210521_incident_report/

### リンクで共有のセキュリティ

- 短かった例
  - ゲーム攻略サイトのチャットがsha1で総当たり攻撃被害を受けたニュース
    - 見つからない・・・・
- 大丈夫そうな長さの例
  - Googleスプレッドシートなどでリンクで共有してみると、256bitのbase64エンコードくらい
- 乱数はどのくらいでぶつかる？の話
  - 想定レコード数と「衝突する確率が十分小さい」をどのあたりに仮定するか、を決めれば、必要なbit数がわかる
  - だいたい256bitだったら十分な理由がわかる
  - https://ja.wikipedia.org/wiki/%E8%AA%95%E7%94%9F%E6%97%A5%E6%94%BB%E6%92%83#:~:text=%E5%95%8F%E9%A1%8C%E3%81%A8%E3%81%AA%E3%82%8B%E3%80%82-,%E6%95%B0%E7%90%86%E7%9A%84%E8%A7%A3%E8%AA%AC,-%5B%E7%B7%A8%E9%9B%86%5D

### 社内向けサービスは、Webアプリケーションフレームワークに到達する前に、認証を入れておきたい話

- log4J
- shellshock
- Struts2の脆弱性
- NextJSの脆弱性(CVE-2025-29927)
  - https://nextjs.org/blog/cve-2025-29927


### なんならSSLも解きたくない話

- heartbleed

### エンジニアの端末のクラウド認証情報は狙われてる話

- いろいろあるはず(探す)


### 認証機能が好きなサービス

- メールアドレスの疎通でログインするタイプのサービス
  - Gather(パスワードを持たない)
- SMSログインで、疎通確認が4桁数字、ログインが6桁数字になってそうなサービス
  - 後で思い出す
- 課金などアカウントをロストしたときの被害が大きくなるタイミングでパスワードの設定やメールアドレス・SMSなどの疎通確認がされるサービス
  - 後で思い出す
- Discord
  - QRコードログイン
- SMSでログインするタイプのサービス
  - YahooID

### 認証関係

- メールアドレス/SMS宛の認証コードでログイン
  - https://pages.nist.gov/800-63-3/sp800-63b.html#:~:text=5.1.3%20Out%2Dof%2DBand%20Devices
    - Out-of-Band-Devices
    - どのくらいのエントロピーが必要でどのくらいでthrottlingすべきかみたいなのが参考になる
- パスワードリセットトークンの実装・長さ
  - https://docs.python.org/ja/3/library/secrets.html#generating-tokens
- セッションの長さ
  - https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#session-id-length
  - uuidv4 は乱数部分が122bitで短い

### GoogleFormの事故

- https://bravegroup.co.jp/news/6359/
- https://scan.netsecurity.ne.jp/article/2024/06/26/51196.html
- https://scan.netsecurity.ne.jp/article/2024/04/22/50908.html
- https://scan.netsecurity.ne.jp/article/2024/06/26/51195.html
TortoiseGitでメッセージのみの空コミットをしたい

# 概要

コーディング終了してコミット。
その後、テストをしてバグが無かった。（ソースコードは一切変わっていない）

コミットする物は何もないが『テストをしてバグが無かった』という記録だけを残すコミットをしたい。

そんな時。

# やり方

左下の ```Message only``` にチェック入れればできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/70cf3eb9-14c7-8ba9-3309-6a009cfa6cdb.png)

# 蛇足

あたいの場合、英語とか用語に慣れるためにTortoiseGitは日本語化してません。

もし日本語化していた場合 ```Message only``` のところはどう表示されるか…
そんなものは知らん。

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2311
TortoiseGit 2.13.0.1
git version 2.38.1.windows.1
GoogleスプレッドシートAPIでforbidden: The caller does not have permission (Google::Apis::ClientError)が出た時の対処法

# どうした？

[こちらの記事](https://qiita.com/kazama1209/items/a08fe0d25384b4a6ea99)を参考に自作のスプシAPIに対してActive Jobを実行したところ、以下のようなエラー文が返ってきました。

```
forbidden: The caller does not have permission (Google::Apis::ClientError)
```

# 解決方法
エラー文を意訳すると「スプシへのアクセス権が無いよ」とのことなので、スプシの共有設定を変更してあげます。
スプレッドシートの右上にある`共有`ボタンを押し、下図の赤枠の箇所を設定します。

![スクリーンショット 2022-11-10 15.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/b364975f-3d34-42a2-19ea-2579027f2426.png)

これにてAPIがスプシにアクセスし、ジョブを実行することができます。

# 参考

https://qiita.com/umeneri/items/0c99c8b09b3e619c8626
Salesforceで分からないことがあれば質問しよう～Trailblazer Community～

こんにちは

この投稿はSalesforce Advent Calendar 2022の3日目の記事です

https://qiita.com/advent-calendar/2022/salesforce

Salesfroceの設定や勉強で分からないことや困ったことがあればみなさんどうしていますか？

今回はSalesfocrceで分からないことがあれば質問できる
 Trailblazer Community の 質問広場～初心者から上級者まで～ 日本
について解説します

今回の内容は動画でも公開されています

https://www.youtube.com/watch?v=VqrSJi0u95s

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


質問するのはとても簡単です

まずはSalesforceにログインしてこちらのリンクをクリックしましょう

https://trailhead.salesforce.com/ja/trailblazer-community/groups/0F93A000000Pd80SAC?tab=discussion&sort=LAST_MODIFIED_DATE_DESC

こちらで
「質問する..」をクリックして質問内容を記載して投稿可能です

添付画像も可能ですのでぜひ詳細まで書いて投稿すれば回答がしやすいと思います


詳細はこちらのヘルプをご確認してください


状況を詳しく伝える
他のユーザが回答しやすいように、状況を詳しく記載してください。
実行した手順や設定内容は、できる限り詳しく記載してください。
エラーが発生した場合は、表示されたエラーメッセージ（または画面のスクリーンショット）を添付してください。
テキストでの説明が困難な場合は、画面のスクリーンショット添付を推奨します。

Trailblazer Communityで他のユーザに質問をする方法
https://help.salesforce.com/s/articleView?id=000383719&type=1



いかがでしたでしょうか

Salesforceを勉強すると、分からないこと結構あるかと思います
そのような場合、ぜひ質問をしてみてはいかがでしょうか
Adobe Illustrator用スクリプトの書き方

イラストレーターをスクリプトで操作する機会があったので、備忘録としてまとめます。

言語はExtendScriptで、JavaScriptの書き方とほとんど同じですが、ECMAScript3に準拠しており、書き方が古いため注意が必要です。

# スクリプト例
## アートボードに四角のオブジェクトを追加
```javascript
// アートボードのx軸20、y軸-30の位置に縦横100の四角のオブジェクトを追加
addRectangle(20, -30)

function addRectangle(x, y) {
  // アクティブのアートボードにグループアイテムを追加
  var groupItems = activeDocument.groupItems.add()
  // 縦横のサイズを12の四角に設定
  var rect = groupItems.pathItems.rectangle(0, 0, 100, 100)
  // 座標の設定
  rect.position = [x, y]
  // 枠線の有無
  rect.stroked = false

  // 色の生成（灰色の場合）
  var color = new RGBColor()
  color.red = 200
  color.green = 200
  color.blue = 200

  // 塗りつぶしの色の設定
  rect.fillColor = color
}
```

## アートボードにテキストを追加
```javascript
// アートボードのx軸20、y軸-30の位置にテキスト「Hello World」を追加
addText(20, -30, 'Hello World')

// テキストの追加
function addText(x, y, text) {
  // アクティブのアートボードにテキストのフレームを追加
  var pointText = activeDocument.textFrames.add()
  // 文字の追加
  pointText.contents = text
  // 座標の設定
  pointText.position = [x, y]
  // 文字サイズの設定
  pointText.textRange.characterAttributes.size = 12

  // 色の生成（赤色の場合）
  var color = new RGBColor()
  color.red = 255
  color.green = 0
  color.blue = 0

  // 文字色の設定
  pointText.textRange.characterAttributes.fillColor = color
}
```

## JSON.stringifyを使えるように
下記サイトの`json2.js`ファイルをダウンロードして、スクリプトファイルと同じディレクトリに配置する。

https://github.com/douglascrockford/JSON-js

```javascript
// JSON.stringifyを使用可能にするためのインポート
#include ./json2.js

var list = [
  {
    name: 'taro',
    age: 10
  },
  {
    name: 'hanako',
    age: 20
  }
]

var json = JSON.stringify(list)
```

## データの保存
```javascript
// 「Hello World」のテキストを保存
saveFile('Hello World')

function saveFile(text) {
  var file
  // 保存ダイアログを出す
  file = File.saveDialog('Export')
  file.open('w')
  file.write(text)
  file.close()
}
```

## グループアイテムの座標を取得
```javascript
var groupRefs = activeDocument.activeLayer.groupItems
var groupPositionList = getGroupPositionList(groupRefs)

// 取得例）
// [
//   {
//     "x": 20,
//     "y": -30
//   },
//   {
//     "x": 50,
//     "y": -100
//   }
// ]

// 全てのグループアイテムのx軸とy軸の座標を取得
function getGroupPositionList(groupRefs) {
  // 空の配列を用意
  var positionList = []

  for (var i = 0; i < groupRefs.length; i++) {
    // 対象のグループアイテム
    var targetRef = groupRefs[i]
    // x軸
    var x = targetRef.visibleBounds[0]
    // y軸
    var y = targetRef.visibleBounds[1]

    var payload = {
      x: x,
      y: y,
    }
    positionList.push(payload)
  }

  return positionList
}
```

# まとめ
座標の取得は、手動だと数が多いと時間がかかりますが、スクリプトだと一瞬で取得できるので便利ですね。

# 参考サイト

http://www.openspc2.org/book/IllustratorCC/

https://ai-scripting.docsforadobe.dev/

https://liginc.co.jp/249449

https://uske-s.hatenablog.com/entry/2018/04/06/141944

# 最後に
### GoQSystemでは一緒に働いてくれる仲間を募集中です！
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=3d219dbe9d6740a77d97
Rustの環境構築した


- Install rustup in my local machine and append to PATH in .zshrc.
- Install rust-analyzer in vs code
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/165ea467-8dc2-9773-8386-91512b337ee1.png)



## Ref

以下に従った。
- [Install Rust - Rust Programming Language](https://www.rust-lang.org/tools/install) 
- [Rust入門者必見！開発環境をセットアップしよう](https://www.youtube.com/watch?v=677kcyyPwJ4)
紙地図とデジタル地図

## はじめに
この記事は#30DayMapChallenge2022 17日目の記事です。
テーマはA map without computerです。
紙地図の特徴をまとめてみます。

![image](https://raw.githubusercontent.com/tjukanovt/30DayMapChallenge/main/images/flyers/30dmc-2022.png)

https://30daymapchallenge.com/

## 紙地図の特徴
- メリット
    - デジタルデバイスがなくても利用できる
    - インターネット回線がなくても利用できる
    - サイズの制約がない
    - 人と共有しやすい
    - 自分専用の地図としてカスタマイズが容易
        - ペンなどで書き込みができる
    - 全体像が分かりやすい
- デメリット
    - 現在位置や目的地を探すのに時間がかかる
    - かさばる
    - 最新の情報の表示が難しい
    - 更新が大変


![image](https://1.bp.blogspot.com/-_Mo8nPV2Bos/WydaErc262I/AAAAAAABMxw/P-oxub4mbPkOr-hC5EZgY81BcxmaF1OTwCLcBGAs/s400/saigai_maq_hinanjo.png)


## デジタル地図の特徴
Google MapsやApple Mapsなどを想像してみます・・

- メリット
    - 現在位置や目的地を探すのが容易
    - デジタルデバイス上で見るため物が増えない
    - 最新の情報を表示できる
    - ルート検索ができる
    - 地物の情報を地図上で閲覧できる
- デメリット
    - デジタルデバイスがないと利用できない
    - デジタルデバイスの電池が切れたら利用できない
    - インターネット回線がないと利用できない
        - オフライン対応しているものもある
    - 詳細の情報を表示するにはズームする必要があることが多い
    - レイヤのオンオフなど操作が必要なことがある

![image](https://3.bp.blogspot.com/-8NKYZTR2p3k/W-VEjTGpRGI/AAAAAAABQGg/NXH8bcXl7AUcuKaDVpzSCidakjdbOCMmQCLcBGAs/s400/smartphone_map_app_woman.png)

## 感想
紙地図は最近触ってなかったですが、デジタル地図と比較すると、デジタル地図にはない良さがありますね。
家庭に1つ紙地図を置いておくことで、避難経路をみんなで確認したり、災害時に持ち込んだり、地理の勉強に役立てたりできそうです。

## 参考文献
https://hakobozu.com/articles/compared-a-paper-map-with-a-smartphone-map-application/
ReactのuseStateで配列やハッシュが更新できない人へ

# はじめに

Reactを触って3ヶ月が経とうとしています。大体のことは思い通りにできるようになってきたと思っていたのですが、久しぶりにuseStateでつまづいたのでまとめます。

割と多くの人が遭遇するのかなと思いました

# 問題

以下のコードのように「いいね数」をボタンで増減できるコードを書きました

今回は「taro」のいいね数だけですが、本来であればハッシュにある全てが1画面に表示されます。


```tsx:App.tsx
import { useState } from "react";
import "./styles.css";

export default function App() {
  const id = "taro";
  const [likes, setLikes] = useState({
    taro: 0,
    hanako: 3
  });

  const countUp = () => {
    likes["taro"] = likes["taro"] + 1;
    setLikes(likes);
    console.log(likes);
  };

  return (
    <div className="App">
      <h1>太郎のいいね数{likes[id]}</h1>
      <button onClick={() => countUp()}>+1</button>
    </div>
  );
}

```

ここで、ボタンを押したときに表示されたいいね数が1増加すると思ったのですが、なぜかされません。

ログを確認したところlikesの中身は変更されていたようなのでsetStateがうまくいっていないようでした。

#解決方法

こちらの記事を見て原因がわかりました


https://gotohayato.com/content/509/

setStateで変更があったと判断する基準がオブジェクト自体なのでオブジェクトが同じlikesの要素を変えても変更が反映されないようです

そこで以下のように新たなハッシュであるnetArrayを作成して、そこに要素を入れてから代入したところうまく動くようになりました。


```tsx:App.tsx
import { useState } from "react";
import "./styles.css";

export default function App() {
  const id = "taro";
  const [likes, setLikes] = useState({
    taro: 0,
    hanako: 3
  });

  const countUp = () => {
    let newArray = {};

    likes.forEach((k, v) => {
      if (k === "taro") {
        newArray[k] = v + 1;
      } else {
        newArray[k] = v;
      }
    });
    setLikes(newArray);
  };

  return (
    <div className="App">
      <h1>太郎のいいね数{likes[id]}</h1>
      <button onClick={() => countUp()}>+1</button>
    </div>
  );
}
```

配列でも同じことが起きそうなのでスプレッド展開するなどして別のオブジェクトに値を移してから代入するようにしましょう

# おわりに

今回は基本に立ち返ってレンダリングされないトラブルに対処してみました。

もっとハッシュを使った更新でいい方法があるような気もしています。
今回のいいねのようなものはどうやっているのか気になりました

# 参考

https://gotohayato.com/content/509/
Unreal Engine関連記事のまとめ

このブログでは、今まで公開された記事の中で、Unreal Engineに関する記事を取り上げ、UE4ガベージコレクション実装原理や実際の応用、そしてUE5の新機能LumenとNaniteの簡単紹介と実装原理、などの記事をまとめます。

---

まずはUE4ガベージコレクション、この記事の著者は南京周潤發で、今は杭州某ゲーム会社のクライアント開発を従事しています。2017年にゲーム開発業界に参入し、MMOやバトルロイヤルゲームの制作に参加。現在、UE4 のモバイル ゲーム開発に携わっており、技術的な学習が大好きで、UE4 と Lua の両方について研究しています。

 

著者の分析に従って、一緒にUE4ガベージコレクションの実装原理を深く分析しましょう。

 

この記事では主に UE4 のガベージ コレクション システムの実現原理を紹介しました。 UE4 は C++ でオブジェクト システムをカプセル化し、リフレクションを追加して C++ ベースのガベージ コレクションを実装します。そのため、開発者は、UObject を使用するときにメモリを手動で管理する必要はありません。効率と利便性を考慮しました、

 

UE4は「Mark Sweep」というGCアルゴリズムを採用していますが、記事ではまず「Mark Sweep」の基本原理を紹介します。 UE4 の GC アルゴリズムは、マーキングとスイープの 2 つの段階に分けることができます。

1)マーキングステージ 

マーキングは、GC アルゴリズムの重要な部分です。 UE4 は「ルート セット」から開始し、参照関係に従ってメモリ内の到達可能なすべての UObject を検索します。検索を高速化するために、一方ではマルチスレッド テクノロジを使用して並列に検索し、他方では ReferenceTokenStream をリフレクションによって生成して、UObject 参照関係をトラバースする効率を向上させます。

2)スイープステージ

到達可能なすべての UObject はマーキング段階で収集され、残りの到達不能な UObject はガベージと見なされ、UE によって削除され、メモリが解放されます。ガベージの後に到達可能になることは不可能であるため、UE はフレームごとにそれらをクリーンアップして、ストールを回避できます。

 

この記事は中級レベルのコースであり、UE4 開発に関心のある読者に適しています。

 

関連コース:

[「Unreal Insights 機能詳細解説」中国語注意](https://edu.uwa4d.com/course-intro/1/195)

説明:
全文は約5,500ワード、読了時間は約40分です。
コースのリリース時間: 2020 年 11 月 4 日

適した読者：
UE4開発に携わるプログラマー
C++の知識があり、C++をベースにGCを実装したい開発者
UE4 オブジェクト システムとリフレクションに関心のある読者

得られる知見:
UE4 GC 原理の分析
関連コードの詳細説明
UE4の使用スキルとプログラミングスキル

目次：
[UE4GCの概要](https://blog.jp.uwa4d.com/2022/04/22/ue4gc%e3%81%ae%e6%a6%82%e8%a6%81/)
[UE4GCのプロセス](https://blog.jp.uwa4d.com/2022/04/22/ue4gc%e3%83%97%e3%83%ad%e3%82%bb%e3%82%b9/)
[スイープのプロセス](https://blog.jp.uwa4d.com/2022/04/22/%e3%82%b9%e3%82%a4%e3%83%bc%e3%83%97%e3%81%ae%e3%83%97%e3%83%ad%e3%82%bb%e3%82%b9/)

理論的な記事の以外、以下のような実用的な記事もあります。

[UE4でどのように漣の効果を作るか](https://blog.jp.uwa4d.com/2022/08/03/ue4%E3%81%A7%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E6%BC%A3%E3%81%AE%E5%8A%B9%E6%9E%9C%E3%82%92%E4%BD%9C%E3%82%8B%E3%81%8B/)

[どうやってUE4で透明な氷を作るか](https://blog.jp.uwa4d.com/2022/08/10/%e3%81%a9%e3%81%86%e3%82%84%e3%81%a3%e3%81%a6ue4%e3%81%a7%e9%80%8f%e6%98%8e%e3%81%aa%e6%b0%b7%e3%82%92%e4%bd%9c%e3%82%8b%e3%81%8b/)

投稿者：落月満江樹

著者のホームページ: https://www.zhihu.com/people/luo-yue-man-jiang-shu-38

UE5に関する記事は以下のよう示します。

[UE5レンダリングの紹介：Nanite編](https://blog.jp.uwa4d.com/2021/11/05/ue5%e3%83%ac%e3%83%b3%e3%83%80%e3%83%aa%e3%83%b3%e3%82%b0%e3%81%ae%e7%b4%b9%e4%bb%8b%ef%bc%9ananite%e7%b7%a8/)

投稿者：洛城

現在 Tencent のゲーム R&D 効率部のエンジンミドルプラットフォーム部門で働いています。

著者のホームページ: https://www.zhihu.com/people/luo-cheng-11-75、

 

[UE5 Lumen実装分析](https://www.zhihu.com/people/jeff-wong-92)

投稿者：Jiff

著者のホームページ: https://www.zhihu.com/people/jeff-wong-92

今まで公開されたUnreal Engineに関する記事は以上です。これからもより多く有益な記事を共有しますから、期待してください。

---

UWA公式サイト：https://jp.uwa4d.com

UWA公式ブログ：https://blog.jp.uwa4d.com

UWA公式Q＆Aコミュニティ(中国語注意)：https://answer.uwa4d.com
emacs + pdf-tools + doom-themes 上で pdf をクリック&ドラッグ → segfault するのをどうにかする

# はじめに

`pdf-tools` が便利そうだと導入してみたはいいものの、 segfault して困ったため備忘録として。


# 環境

-   MacBook Air M1 2020
-   macOS Ventura (13.0.1)
-   Emacs Plus 28.2
    -   テーマの管理に `doom-themes` を使用


# 原因

ネットで検索してもそれらしいものがない + まっさらな状態から `pdf-tools` 導入しても再現しなかったため、 emacsen ではなくプラグインを疑った。
怪しそうなプラグインを探すうち `doom-themes` が原因っぽいと判断。
さらに dark theme では再現するが、light themeでは再現しないようだった。

そこで、 dark theme 使用時に `pdf-view-dark-minor-mode` を有効化したところひとまず segfault はしなくなった。
しかしテーマの変更時にいちいち minor-mode を気にするのも煩わしいため、背景がニュートラルグレーより暗っぽければ dark theme と判断し minor-mode を有効化する方向で解決を試みた。


# 解決

コードは以下。
パッケージの管理には `leaf.el` を使用している。

```emacs-lisp
(leaf *switch-pdf-view-dark :after doom-themes
    :doc "detect whether doom-theme bg color seems dark"
    :preface
    (defun theme-seems-dark-p ()
    "Check `(doom-theme 'bg)'. If theme seems to be dark, returns t"
    (< (apply '+ (color-name-to-rgb (doom-color 'bg))) 1.5))
    :hook
    (pdf-view-mode-hook    . (lambda ()
                                (if (theme-seems-dark-p)
                                    (pdf-view-dark-minor-mode +1)
                                (pdf-view-dark-minor-mode -1))))
    (after-load-theme-hook . (lambda ()
                                (dolist (buff (buffer-list))
                                (with-current-buffer buff
                                    (when (eq major-mode #'pdf-view-mode)
                                    (if (theme-seems-dark-p)
                                        (pdf-view-dark-minor-mode +1)
                                        (pdf-view-dark-minor-mode -1)))))))
    )
```

`doom-color` は `doom-themes` に含まれる関数であり、 `(doom-color 'bg)` によって現在 `doom-themes` で適用している theme の背景色を取得する。
`theme-seems-dark-p` で theme が light か dark か判定しており、非常に大雑把だが背景色の RGB 値がニュートラルグレーの RGB 値合計より小さければ dark theme だろう、としている。
`after-load-theme-hook` は `load-theme` 実行後に発火する自作 hook。
theme の確認、 minor-mode 適用は `pdf-view-mode` と `load-theme` 後に行なわれる。
`load-theme` 時に `pdf-view-mode` のバッファがあれば背景色を取得し、必要に応じ minor-mode を適用する。


# おわりに


ひとまず動作に支障はなくなったものの、 `pdf-tools` のみをインストールした最小構成下において `adwaita-dark` を `load-theme` しても問題は発生しなかった。
vanilla なテーマ管理下では dark theme を使用しても `pdf-view-dark-minor-mode` は不要なようだ。
`doom-theme` 側での face の扱いに何かあるのかもしれないが、とりあえず動くのでヨシ。


プライグイン絞り込みの際、有効、無効の切り替えを効率よくできたのは `leaf.el` のおかげで、とても有り難みを感じた。作者さんには足を向けて寝られない……


# 参考

-   [vedang/pdf-tools](https://github.com/vedang/pdf-tools): Emacs support library for PDF files.
-   [doomemacs/themes](https://github.com/doomemacs/themes): A megapack of themes for GNU Emacs.
-   [d12frosted/homebrew-emacs-plus](https://github.com/d12frosted/homebrew-emacs-plus): Emacs Plus formulae for the Homebrew package manager
-   [conao3/leaf.el](https://github.com/conao3/leaf.el): Flexible, declarative, and modern init.el package configuration
ESP32をパスワード付きのアクセスポイントにする

# 目的
今回はESP32をパスワード付きのアクセスポイント（AP）にする．パスワード付きのアクセスポイントにすることで、Wi-Fi接続を任意のデバイスのみと行える．

# 構築環境
- ESP32
    - マイクロコントローラ
- MicroPython(1.19.1)
    - 使用したプログラミング言語

# パスワード付きのアクセスポイントにするプログラム
```python
import esp    
import network, machine

#SSIDを作成
ssid = 'ESP_retasu'
#パスワードを作成
password = 'caJuApda'
#IPアドレスを作成
IP = '192.168.5.5'      

#インスタンスの作成
ap = network.WLAN(network.AP_IF)
#アクセスポイントインターフェースをアクティブにする
ap.active(True)            
#Wi-Fiの設定（SSID、パスワードの種類、パスワードの値）
ap.config(essid = ssid, authmode = 3, password = password)
while ap.active() == False:
  pass
#Wi-Fiのアクセスポイントを立ち上げ成功メッセージ
print('Connection is successful')
#アクセスポイントの情報を取得
ap.ifconfig((IP,'255.255.255.0',IP,'8.8.8.8'))
#アクセスポイントの情報を出力
print(ap.ifconfig())
```

# authmode
先程のプログラムに記述してあったauthmodeがパスワード付きのアクセスポイントにするために重要なポイントである．authmodeには5つの値が設定されており下記に記述する．
- 0--open
    - パスワードを設定しない
- 1--WEP
    - 5桁の半角英数字を設定できる
- 2--WPA-PSK
    - 8桁以上の半角英数字でパスワードを設定できる
- 3--WPA2-PSK
    - 8桁以上の半角英数字でパスワードを設定できる
    - WPA-PSKよりもパスワードが盗聴されにくい 
- 4--WPA/WPA2-PSK
    - 8桁以上の半角英数字でパスワードを設定できる
    - 小規模ネットワークに適している

# 結果
上記のプログラムを実行して以下の通りに出力されたら成功である．
![qitta1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2248947/c66538ac-3d23-fa2c-18bd-4482517cd2f3.png)
スマートフォンで接続できるWi-Fiを検索した場合，上記のプログラムで設定した”ESP_retasu”が表示されている．またWi-Fiのアイコンに鍵のアイコンが付随しているのでパスワードが設定されているのが分かる．
![165494.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2248947/d718e089-2778-0498-230a-74e421f4043f.jpeg)
【Scala】標準出力で文字色の変更・出力文字を消す【ANSIエスケープシーケンス】

## 色の変更
　標準出力で色の変更をする。出力したい文字列の前に `\u001b[31m` と書くと, 赤色で文字が出力される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2675371/2377e435-8502-0152-1efd-64bf8ce58f83.png)

　以下の通り様々な色へ変更できる。`\u001b[0m`で文字色のリセットができる。
||文字色|背景色|
|-|--|--|
|黒|\u001b[30m|\u001b[40m|
|赤|\u001b[31m|\u001b[41m|
|緑|\u001b[32m|\u001b[42m|
|黄色|\u001b[33m|\u001b[43m|
|青|\u001b[34m|\u001b[44m|
|マゼンタ|\u001b[35m|\u001b[45m|
|シアン|\u001b[36m|\u001b[46m|
|白|\u001b[37m|\u001b[47m|

## 出力文字の消去
```scala:scala
for (i <- 1 to 10) {
    println(i)
    Thread.sleep(1000)
    print("\u001b[1F\u001b[2K")
}
```
　これを実行すると、1, 2, ..., 10 と順に数字が表示される。

　**i** を出力して **println** によって改行された後、`\u001b[1F`で1つ上の行にカーソルを移動させ、`\u001b[2K`で **i** を出力した行の文字を消去している。

　ここで使ったエスケープ文字の意味は以下の通り。
|内容|記法|
|-|-|
|行全体を消去|\u001b[2K|
|1行上の行の先頭にカーソル移動|\u001b[1F|
|今の行の先頭にカーソル移動|\u001b[G|

## 参考
　色んなANSIエスケープシーケンスが載っている。

https://qiita.com/PruneMazui/items/8a023347772620025ad6

https://qiita.com/exy81/items/99e99ab8c184343948cc
外に出よう！勉強会に参加しよう！ - スクラム一年目でRSGTに参加してよかったことを振り返ってみた。

# みんな！お出かけしようぜ！
今年は一月のRSGTに参加して以来、一年を通してオンラインオフライン関係なく勉強会やカンファレンスに参加する機会が増えました。
以前までは勉強会に対してあまり効果や意味を感じられなかったんですが、
RSGTは効果と意味をめちゃくちゃ感じることができて、ほんとよかったんですよ！

マジでみんな、外に出るといいことあるよ！というのが言いたくて、参加後すぐに社内LTしました。
そこから一年が経とうとしている今、改めて内容を見直しつつ、記事にまとめてみた次第です。
では、はじまりはじまり。

# RSGT (Regional Scrum Gathering Tokyo) について
スクラムを実践する人が集い
垣根を超えて語り合う場所

であり

日本全国からスクラム、アジャイルに関する一流の人たちと、
スクラムを実践する開発者が集まって各々の知見を共有する会

でした

くわしくはこちら。まもなく来年一月にも開催されますので現地で会いましょう！
https://2022.scrumgatheringtokyo.org/


# なんでRSGTに行ったのか。その前談
弊社toCプロジェクトの開発体制が変更になる際、大塚が
「スクラムやりましょう！前に体験して開発の進行がスムーズだった(というよりは「はたから見てスムーズに見えた」)ので！ついでにスクラムマスターやります！」
という感じで昨年九月からスクラムを始めました(雑

### 始めた時の私の状態
* スクラム開発は少し経験した程度(デザイナーなので厳密にはスクラムチームの横に添えて居る感じ)。
* スクラムマスターは初めて経験
* ほぼ独学でやるしかない。
* 社内にスクラムの知識を持った人無し。
* だが開発は進めないといけない！

そんな感じでスクラムマスターを始めました。
日々書籍やネットの情報と睨み合い、ブン回していかないと開発が！進まない！！必死！！！

時々、知見のある社内外の先輩に泣きついていたのですが、
一人の先輩が「RSGT行ったほうがいいよ！」と言ったのをきっかけに、
なんかよーわからんけども藁をもすがる思いで¥35,000を振り込み、
雪の降るお茶の水へ歩を進めたのでありました。

# 結論：お出かけしてよかった！
### RSGTでやってたことの一例
* アジャイル、スクラムに関する本を書いている著者、大企業でスクラムマスターを育てるコーチなど、一線の人たちによる講演
* コーチによるなんでも相談会「コーチズクリニック」
* 交流会
* Open Space Technology (OST) etc...

### 私は何した？どう過ごしていた？
* 一日目：ひたすらに講演を聴き内容をメモる。懇親会で5人と知り合った。
* 二日目：Gatheringの意味を生かすべく、ブースの人や講演者の人に話しかけまくる！著名な方々とも知り合う。
* 三日目：OSTでブースを仕切り、ファシリテート！さらに知り合いが増える。
**→その結果、最終的に30人くらいスクラムマスターの知り合いができた！**

# 勉強会というものに行って得たこと、考えたこと
### その1 知識を得て、仲間を得た
行く目的は
- **最新バージョンの技術を知り、自分のスキルを上げる**

だったのだが、結果として

- **会社の外に、自分と同じ目的や悩みを持った人を見つけられた**

のはとてもよかったです。

### その2 得た知識についてその場で深堀り、振り返ることができた
聞いた講演はいろいろありましたが、自分で書き留めるだけでなく、講演・得た知識について他人と即話せるのがよかったです。
自分の場合、メモ書くだけだとどうしても自己満で終わって忘却してしまうことも多く。
人と話すことで、頭に定着させたり、応用的に知識を広げて解釈、咀嚼できた感じがしました。

誰かと行く、または現地で仲間を得て話をするの、オススメ！！

### その3 レベル高っけえ話が聞けた
そりゃ当たり前だろうというのは思うんですけど、すごく大事だったので。

レベルの高い人の話を聞くことで起こったことは
- 自分のレベルを知れた(自分と講演者の差を客観視できた)
- 新しい知識で自分の技術を引き上げてもらえた
- 困った時に相談できる人と知り合えた(あいさつは大事！)

### その4 勇気を出して自分もアウトプットできた！
アウトプット大事！ 
今回はOpen Space Technologyという、誰でも何かについて話せる機会があったり、
スタッフさんたちが声をかけてくれたりと、講演者ではない自分もアウトプットのチャンスをもらいました。

悩みも、弱みも、強みもすべて曝け出し、話に出していく。そうすると自分の中が整理できる。
社内で一人で考えてると悶々としてしまうこともありますが、それも話の種にしてアウトプット。
すると色々な人が手を差し伸べてくれたり、共感してくれたり、そうして解決する悩みもたくさんありました！


# まとめ
- 外に出よう！勉強会に参加しよう！
- 講演を聞こう。メモを取ろう。
- いろんなひとにあいさつしよう。お友達が増えるかも！
- 聞いたことについて、すぐに誰かと話そう！
- 学んだことは文章にまとめたり、発表しよう！
- あとはモチベーションが上がった自分を使って日々、実践しよう！


という感じでございました。

たまには外で刺激を得て、自分にも会社にもいいことしていきましょう！
Next.jsでお手軽テックブログを作った

# はじめに

私が勤めている企業ではなぜかテックブログがありません
普段からアウトプットしている人も恐らく私だけという状態なのでテックブログがあったとして書く人がいないのでなかったのかと思います

しかし最近になってエンジニア採用をするならどんな技術がその企業でできるのだろうという理由からテックブログを見るのは当たり前だということに気づきました
テックブログがない私の会社では強いエンジニアが採用を受けることがほぼありません

そこで学習の一環として勝手に会社のテックブログをNext.jsで作成してみたので記事にします

# 作成したもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/fd954c1f-c58c-97b2-b61f-e158ca757ad9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/de372160-4306-fa5e-3332-cfaf8124f01f.png)

これがトップページのイメージです。
ブログには大きく2つの種類があり、ブログ用に投稿している記事とQiitaやZennなどに投稿している記事が掲載されるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/68820b27-2698-8a27-ebfa-737da95d10b2.png)

記事の詳細画面ではMarkdown形式のものをHTMLとして表示できるようになっています。

# 使用した技術

今回はMarkdownブログを作ろうと思ったのでNext.jsのSSGを利用して作成しようとしました
また、RSSでデータを取得して外部サイトの記事も取得することで、アウトプットの場所を自由に選べるようにしています

## 外部サイトをRSSからブログにする

ここの実装はほとんど以下の動画を参考にして行いました

https://www.youtube.com/watch?v=lI8CjHspGFU&t=0s

この動画では5時間モブプログラミングをして1からテックブログをTDDで作成しています。
動画を真似るだけでRSSからブログが作れるだけではなく、TypeScriptの方の話やTDDのやり方、サーバーのモックやCypressを使ったE2Eなど多くのことが学べました
この動画で勉強するのはかなりのステップアップになるのでお勧めです

kawamataさんが実装の方針や考えていることをしっかり話してくれたり、実際に調べながら実装していくのもよかったので、別の企画も楽しみにしています

話は逸れてしまいましたが、この動画をやることでRSSから情報を取得して画面に表示するまではできるのであとはいい感じにCSSを当てて表示するだけでRSSブログは簡単にできます

また以下の記事も大変参考になりましたので共有しておきます

https://zenn.dev/catnose99/articles/cb72a73368a547756862

## Markdownブログを作成する

ブログをつくるならNext.jsでSSGをつかったMarkdownブログと決めていました (流行りだとおもってます)
そこで以下の動画をみてNext.jsの学習を行いました

https://www.udemy.com/course/nextjs-microblog-for-beginner/

この動画の作者の方はとても分かりやすい説明と無駄のない説明がとても好きでReactを学習する際には大変お世話になっております。

このブログではまさにやりたかったMarkdown, SSGなのでこの動画をみて真似ればブログが完成します

## 2つを併せる

ほとんどできているものをあとは組み合わせるだけで今回のブログは完成しました
Next.jsのCSSはMantineというコンポーネントライブラリを利用してみました

1から技術を調べてやるのもよいですが、既にハンズオンとして存在するものをコアの技術としてアレンジを加えるという個人開発の方法もとても早く作れるので良いなと思いました

# おわりに

他にもデプロイはFirebaseで、CI/CDにDaggerを利用したりと新しいことも実はやっておりますが、今回はコアな部分の簡単な紹介でした
自分で何かものを作り上げる経験がほぼなかったので、とても達成感がありました
今後も色々個人で開発していければと思ってます

# 参考

- [#1 TDD & Next.jsで公式テックブログを1から作る(LAPRASモブプロ生配信)](https://www.youtube.com/watch?v=lI8CjHspGFU&t=0s)
- [チーム個々人のテックブログをRSSで集約するサイトを作った（Next.js）](https://zenn.dev/catnose99/articles/cb72a73368a547756862)
- [【Next.js入門】ReactフレームワークのNext.jsでマイクロブログを構築しながら基礎と本質を学ぶ講座](https://www.udemy.com/course/nextjs-microblog-for-beginner/)
TypeScript + Serverless で VSCode debug

ここに一応書いてある:

https://www.serverless.com/plugins/serverless-offline#debug-process

このお勧め設定

```
{
  "type": "node",
  "request": "launch",
  "name": "Debug Serverless Offline",
  "cwd": "${workspaceFolder}",
  "runtimeExecutable": "npm",
  "runtimeArgs": ["run", "debug"],
  "sourceMaps": true
}
```

を使えば、実行ボタンを押した時に `npm run debug` が実行されるので package.json に実行スクリプトを書けば良い。この際に

* 環境変数 SLS_DEBUG=* をセットする。
* node --inspect オプションをセットする。

必要があるので `package.json` の `scripts` セクションに次のような物を追加すれば良い。

```
"debug": "SLS_DEBUG=* node --inspect node_modules/serverless/bin/serverless.js offline start",
```

ここで、`--inspect` というのは node がデバッグ情報を提供するオプションらしいのだが、なぜか無くても動く(あとで調べる)。なのですでに `npm start` に起動スクリプトがあれば

```
"debug": "SLS_DEBUG=* npm start",
```

でも動く。あと、TypeScript を使っている場合は tsconfig.json に `"sourceMap": true,` が必要。

```
{
  "compilerOptions": {
    ...
    "sourceMap": true,
  },
  ...
}
```

ちなみに、Auto Attach が有効になっている場合(default)、何もしなくてもターミナル内で node を動かせば勝手にデバッガが動き出す。なので `sourceMap: true` さえあれば `npm start` だけでもデバッグ自体は可能。ただ微妙に表示が見にくい。

参考

* https://code.visualstudio.com/docs/nodejs/nodejs-debugging
* https://www.serverless.com/plugins/serverless-offline#debug-process
[ROS2 foxy] c++とpython共存パッケージのテンプレート

ROS2では，c++とpythonのパッケージの書き方は異なる．
実際には，同じパッケージ内で，どちらの言語も使いたいということがある．

表面的にチュートリアルをやっただけだと，共存の方法はわからなかった．

ということで，共存パッケージのテンプレートを作ってみた．
参考にして欲しい．

なお，今回のパッケージは以下のリポジトリにアップしている．

https://gitlab.com/ros2_tips/ros2_base_pkg

# パッケージ構成

一般的なROS2の構成と同様です．
cppのソースコードは，srcフォルダ，
pythonのソースコードは，scriptsフォルダに入れます．

```txt:パッケージ構成
src/
    cpp_node.cpp
scripts/
    py_node.py
ros2_base_pkg/
    __init__.py
    import_module.py
include/
CMakeLists.txt
package.xml
```

## import_module.py

```py:import_module.py
#!/usr/bin/env python3

from ros2_base_pkg.import_module import ....
```

## CMakeLists.txt

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(ros2_base_pkg)

if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

#-- Dependencies
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclpy REQUIRED)

#--- for C++
include_directories(include)
add_executable(cpp_node src/cpp_node.cpp)
ament_target_dependencies(cpp_node rclcpp)

install(TARGETS
  cpp_node
  DESTINATION lib/${PROJECT_NAME}
)
#--- end C++

#-- for Python
ament_python_install_package(${PROJECT_NAME})

install(PROGRAMS
  scripts/py_node.py
  DESTINATION lib/${PROJECT_NAME}
)
#--- end Python

ament_package()
```

## package.xml

```xml:package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>ros2_base_pkg</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="your@email.com">Name</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  <buildtool_depend>ament_cmake_python</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>rclpy</depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>
```

# 参考

- How to create a mixed C++ and python ament package
https://github.com/bponsler/ros2-support/blob/master/tutorials/creating-a-mixed-cpp-and-python-package.md
TypeScriptでneverを検知する

# はじめに
TypeScriptを使っているとnever同士比較をしたい時があります。しかし、neverは他の型と異なり少々工夫して比較する必要があります。この記事では型の比較を使用する一例として、引数の型がneverであることを確認する型を解説します。

# 解説
neverであることを確認するコードは下の通りです。
```ts
type IsNever<X> = X[] extends never[] ? true : false;
```
下のような他の型であることを確認のためのコードは動きません。
```ts
type IsNever<X> = X extends never ? true : false;
```
## Conditional Types
まず[Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)の仕様を見ていきます。Confitional TypesはTypeScriptの型システムの中で条件型としての役割を担っています。例として下のようなコードを考えます。
```ts
type Compare<X> = X extends Y ? true : false;
```
このコードはXがYに割り当てることが可能な場合にtrueを不可能な場合にfalseを返すようになっています。このような比較して型を抽出することをConditional Typesと言います。条件型としての役割を持つだけあって確かに`X extends Y`を条件式とした場合三項演算子と似た形式ですね。
さて、このConditional Typesには面白い仕様があります。Xにユニオン型を渡した時の挙動を想像してください。例えば下のように型を受け取ってその型で配列を作成する型に、ユニオン型を引数として渡すことを考えます。
```ts
type ToArray<Type> = Type extends any ? Type[] : never
type TypeScript = ToArray<'type' | 'script'>
```
この時`TypeScript`の型はどうなるでしょうか。これから説明する仕様を知らない場合`('type' | 'script')[]`となると考えられます。しかし、この結果は`'type'[] | 'script'[]`となります。これはXがユニオンの場合二つに分かれることに起因しています。つまり`'type' | 'script' extends any`は`'script' extends any | 'script' extends any`のように別れて評価されます。この仕様を[Distributive Conditional Types
](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types)と言います。

## never
次はneverについて考えていきます。neverがstringとユニオン型を取ることを考えてください。`string | never`これが使用されるときは使用者は`string`として扱います。つまりneverは空(ないもの)として扱われるわけです。そのためneverをユニオン型として扱おうとした時、空として扱われます。

## 結論
以上のConditional Typesの仕様とneverとユニオンの仕様を組み合わせて考えると、Xがneverだったときこの型は` extends Y`と分離されて、空との比較になってしまします。そのため、`never extends never ? true : false`は` extends never ? true : false`となってfalseを返すようになってしまうわけです。
そこで、neverを直接比較せず、`never[]`や`[never]`のようにして比較することを考えます。neverをユニオンとして扱うとからですが、`never[]`や`[never]`をユニオンとして扱った場合は配列ですので空になりません。そのため最初に紹介した
```ts
type IsNever<X> = X[] extends never[] ? true : false;
```
が有効となります。察しの通り
```ts
type IsNever<X> = [X] extends [never] ? true : false;
```
でも有効な結果が返ってきます。
【JavaScript】setTimeoutから返るIDは絶対0じゃないし、clearTimeoutに0を渡しても何もしない

超小ネタです。JavaScriptのタイマー系関数に`setTimeout`と`setInterval`があります。これらは返り値として数値型のタイマーIDを返し、このタイマーIDを`clearTimeout`及び`clearInterval`に渡すことでタイマーをキャンセルできます。

この**タイマーIDは0よりも大きいことが保証されています**。また`clearTimeout`または`clearInterval`に無効なタイマーIDを渡しても何もしないことも保証されています。（以下参照）

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers

なのでタイマーを使っていないときはタイマーIDに0を代入しておけば、`clearTimeout`を使うときに毎回タイマーを起動しているかをチェックするようなコードは不要です。

```javascript:このようなコードは基本的に不要
if(timerId != null) {
  clearTimeout(timerId);
}
```

この事実は例えばsetTimeoutの用途として頻出するスロットリングをするときのコードをちょっとだけ短くできます。

```diff_javascript
-let timerId = null;
+let timerId = 0;
 function onInput(text) {
-  if(timerId != null) {
-    clearTimeout(timerId);
-  }
+  clearTimeout(timerId);
   timerId = setTimeout(async () => {
     await sendRequest(text);
   }, 500);
 }
```

ちなみにTypeScriptの場合は、型注釈が不要になるというメリットが追加であります。

```diff_typescript
-let timerId: number | null = null;
+let timerId = 0;
 function onInput(text) {
-  if(timerId != null) {
-    clearTimeout(timerId);
-  }
+  clearTimeout(timerId);
   timerId = setTimeout(async () => {
     await sendRequest(text);
   }, 500);
 }
```

微々たる差ですが条件分岐はなるべく少ないほうが良いですし、無意味な処理をするコードは1行でもあるべきではないので知っておく価値はあると思います。
MySQLでテーブルを作成した。

<br>
<h2>MySQLでテーブル作成するコマンド</h2>

```
	CREATE TABLE <テーブル名> (
		<列名1> <データ型> <制約>,
		<列名2> <データ型> <制約>,
		<列名3> <データ型> <制約>,
) <テーブルオプション>
```

<h3>列名</h3>

登録するデータの項目名

|名前|性別|生年月日|血液型|
|:--|:--|:--|:--|
|山田 太郎| 男性|1990年10月10日|B型|
|吉田 香|女性|1997年5月7日|A型|
|田中 賢|男性|2002年6月21日|O型|
|中村 康太|男性|1999年8月31日|AB型|

上の表でいう、名前、性別、生年月日、血液型 の部分。

<h3>データ型</h3>

登録するデータの種類を定める。

文字列なのか、整数なのか、日時なのか とか。

<h3>制約</h3>

登録するデータに条件や制限をつける。

空欄は禁止とか、同じデータは入れてはいけないとか。

<h3>テーブルオプション</h3>

テーブルのオプションを指定する。

何語でデータを登録するのか とか。

<h2>テーブルの例</h2>

```sql
	CREATE TABLE reviews (
    id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    author VARCHAR(255),
    status VARCHAR(10),
    score INTEGER,
    comment VARCHAR(1000),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARACTER SET=utf8mb4;
```

<h3>データ型で使用しているもの</h3>

<b>INTEGER</b>

データの型は、整数。

<b>VARCHAR</b>

データの型は、文字列。

(数字)は、文字数の制限。

<b>TIMESTAMP</b>

データの型は、日付と時間

<h3>制約で使用しているもの</h3>

<b>NOT NULL</b>

項目は必ず入力する。

<b>AUTO_INCREMENT</b>

データを追加したら、現在格納されているデータ数+1をする。

<b>PRIMARY KEY</b>

重複なし。同じデータはダメ。

<b>DEFAULT CURRENT_TIMESTAMP</b>

対象の列に何も入力がされなかったら、現在の時刻を入れる。（厳密には違う）

<br>
<br>
<br>

ざっくりと説明しましたが、厳密に知りたい方は公式ドキュメントを参照してください。

<h2>参考</h2>

[独学エンジニア](https://dokugaku-engineer.com/)
[MySQL公式ドキュメント](https://dev.mysql.com/doc/)
PythonからVantageに接続する

[Teradata® Package for Python Function Reference](https://docs.teradata.com/r/Teradata-Package-for-Python-Function-Reference/April-2022) [リリース番号：17.10　リリース日付：2022/4]の翻訳です。

# はじめに
PythonからTeradata Vantageに接続する方法を説明します。
ライブラリとして[teradataml](https://pypi.org/project/teradataml/)を利用します。

:::note info
**teradataml**はTeradata Vantage用のPythonライブラリです。
:::

# 基本操作
## Vantageに接続する
```python:python code
# 接続用ライブラリの宣言
import teradataml as tdml
# データベース接続
tdml.create_context(host = "IPアドレス",username='ユーザ名',password='パスワード')
```

## 接続情報を確認する
```python:python code
# 接続情報の表示
tdml.get_context()
```

<details><summary>結果を表示</summary>

```
Engine(teradatasql://ユーザ名:***@IPアドレス)
```
</details>

## Vantageから切断する
```python:python code
# データベース切断
tdml.remove_context()
```

# おわりに
:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

## Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
Teradata VantageのPythonライブラリ(teradataml)をさわってみよう

[Teradata® Package for Python Function Reference](https://docs.teradata.com/r/Teradata-Package-for-Python-Function-Reference/April-2022) [リリース番号：17.10　リリース日付：2022/4]の翻訳です。

# はじめに
PythonでVantageのデータを取得する方法を説明します。
ライブラリとして[teradataml](https://pypi.org/project/teradataml/)を利用します。

:::note info
**teradataml**はTeradata Vantage用のPythonライブラリです。
:::

# 1). teradatamlのインストール
Pythonおよびpipがインストールされている環境でインストールを開始します。
## pipコマンドによるライブラリの入手
```
pip install teradataml
```

# 2). 基本操作

## データベースの基本操作
|#|タイトル|関連コマンド|
|:-|:-|:-|
|1|[PythonからVantageに接続する](https://qiita.com/tmsky/items/880c8a9ffb69b73cd325)|create_context,remove_context|
|2|[PythonでVantageのデータを取得する](https://qiita.com/tmsky/items/74b20566ce7ddca04338)|from_table,from_query|

:::note warn
基本操作の詳細記事は順次追加予定です。
:::

## データフレームの基本操作
|#|タイトル|関連コマンド|
|:-|:-|:-|
|1|[teradatamlデータフレームでCSVファイルをテーブルにロードする](https://qiita.com/tmsky/items/fd5746833afa751901b7)|to_sql|
|2|[teradatamlデータフレームから基本統計量を出力する](https://qiita.com/tmsky/items/40ffb988ccabf9cfe4b8)|describe|
|3|[teradatamlデータフレームで新しいカラムを追加する](https://qiita.com/tmsky/items/dcb13e2bf9db7243cb14)|assign|
|4|[teradatamlデータフレームからデータを抽出する](https://qiita.com/tmsky/items/fff3d29f4c8d7cf704b4)|select,loc|
|5|[teradatamlデータフレームを結合する](https://qiita.com/tmsky/items/f0f7a76c2cb92024eb07)|join|
|6|[teradatamlデータフレームをpandasデータフレームに変換する](https://qiita.com/tmsky/items/7dcd6a35b812311d4d2b)|to_pandas|

:::note warn
基本操作の詳細記事は順次追加予定です。
:::

# おわりに
:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

## Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
Expoでeas buildする時はversionCodeを動的にインクリメントしようぜ

# やりたいこと
- 以前、[ExpoでiOSアプリをeas buildする時はbuildNumberをapp.config.tsで動的に設定すると楽だよって話](https://qiita.com/0ba/items/22fb052e1c3737295b2a)という記事を書いた。
- これはExpo上でiOSアプリのbuildNumberを日付にすることで、eas buildするたびに手動でインクリメントする必要がなくて楽だという記事。
- しかし、buildNumberのandroid版であるversionCodeは最大値の問題で同じ戦略は取れなかった。
- 今回はその問題を解決する。


# app.jsonのversionCodeをインクリメントするスクリプトを用意する
力技感があるが、今回はapp.jsonを丸ごと書き換えてしまうという作戦をとることにした。

以下のscriptをプロジェクトのルートに用意する

```updateAndroidVesionCode.ts
const fs = require("fs")

const appJson = JSON.parse(fs.readFileSync("./app.json", "utf8"))
appJson.expo.android.versionCode += 1
fs.writeFileSync("./app.json", JSON.stringify(appJson, null, "  "))

```

app.jsonを読み込んできて、versionCodeを1インクリメントし、保存するというスクリプト


# package.jsonをスクリプトを実行するように書き換える

これをeas buildの前に実行すればよいので、package.jsonを以下のように書き換える

```package.json
{
  "name": "hogehoge",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    ~省略~
    "build:android": "node updateAndroidVesionCode.ts && eas build  --platform android",
    "test": "jest",
    ~省略~
  },
  ~省略~
}
```


# まとめ
iOSのbuildNumberも同じやり方ができるはずなので、これからExpoでアプリを作る人はそうすると良いと思う。
自分はiOSのほうは日付を使ってしまっているので、そのまま日付を使い続けるしかないが。

# 追記
この記事を書き終わって数日後にExpoが公式で自動インクリメントをサポートしてることを知った。
https://docs.expo.dev/build-reference/app-versions/

ちなみにこの設定を導入している個人開発アプリは↓です
[【個人開発】「後で」返事ができる文通チャットアプリ「レイター」を作った話：技術編](https://qiita.com/0ba/items/2dc7eb1e7f16289ae739)

Twitterもやってるので、よければフォローお願いします。
→https://twitter.com/ObataGenta
paiza.ioでelixir その78

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

# 練習問題
e-statのsparqlを叩いて、緯度経度から、住所を求めよ。

# サンプルコード

```
:inets.start
:ssl.start

query = URI.encode_query(%{query: """

PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>
PREFIX dcterms:<http://purl.org/dc/terms/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX ogcf: <http://www.opengis.net/def/function/geosparql/>
select ?municipality ?area
where {
    ?s <http://www.opengis.net/ont/geosparql#hasGeometry> ?polygon ;
     rdfs:label ?area ;
     dcterms:isPartOf / rdfs:label ?municipality .
    ?polygon geo:asWKT ?geom .
    FILTER (ogcf:sfContains(?geom, "POINT(140.0 38.0)"^^geo:wktLiteral)) .
    FILTER (LANG(?municipality)='ja') .
}

"""})
#|> IO.inspect
{:ok, {{_, _, _}, _, body}} = :httpc.request(:post, {
	'https://data.e-stat.go.jp/lod/sparql/alldata/query', 
	[{'Accept', 'application/sparql-results+json'}], 
	'application/x-www-form-urlencoded', 
	query
}, [], [])
#|> IO.inspect
body = IO.iodata_to_binary(body)
IO.puts(body)


```

# 実行結果

```
{
  "head": {
    "vars": [ "municipality" , "area" ]
  } ,
  "results": {
    "bindings": [
      {
        "municipality": { "type": "literal" , "xml:lang": "ja" , "value": "川西町" } ,
        "area": { "type": "literal" , "xml:lang": "ja" , "value": "大字上小松" }
      }
    ]
  }
}

```

# 成果物

https://paiza.io/projects/zLunOt1EodvxhuXdoNhQTg?language=elixir


以上。
プロジェクトマネジメントでのリスク管理の極意

![スクリーンショット 2022-11-17 11.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/cbff7a61-c063-b76c-f9d8-59b5d997b0ff.png)


プロジェクトマネジメントは、色々とスキルが必要です。
・コミュニケーション能力
・交渉力
・チーム管理
・リスク管理
・問題解決能力
・予算管理
等、他にも沢山ありますが、結構、手抜きされるのがリスク管理でもあり、下手なプロマネの人をよく見ます。

**今回の記事は、このリスク管理の極意について話たいと思います。**

世の中は不確実性に満ちてます。100%の事なんか存在しません。
・ロシアが戦争を始めたり
・コロナで一斉に各国が鎖国を始めたり
人間が行きていくためには、この不確実性と向き合ってコントロールする必要があります。

# 先ずは未来を予想してみる
未来を予想してみると色んなパターンが見えてくると思います。
例えば、旅行に行く事に対して、
天気　→　晴れ、曇、雨
道　→　快適、渋滞、事故渋滞
体調　→　快適、寝不足、風邪気味
場所　→　想像以上、思ってたとおり、期待はずれ、大混雑、空いてなかった
考え出すとキリがありません。世の中はコントロール出来ない大量の変数が溢れてます。

# 次は確率を計算してみる
色んなパターンで良いことが起きる確率と悪い事が起こる確率があるので、その確率を計算する事にしてみましょう。
思ってたよりも起こる確率が高かったり、低かったり。
思ってたよりも起こる確率が高確率だったり、レアだったり。
思ってたよりも起こる確率が幅広かったり。
確率を計算してみると意外な部分に気付いたり、安心出来たりする事もあるでしょう。

# 対策を考えてみる
各パターンの出来事に対しての対策を考えてみて下さい。
晴れなら日焼け止め。薄着。雨の対策は、傘を持ったり、少し暖かい服装をしたり、来たり脱いだりできる服装をしたり。
場所は、事前に調べて期待値の調整をおこなったり、人に聞いてみたり。外れだった時のために別の場所の案を検討したり。
もちろん、パターンの中にはよくわからない出来事も起こると思います。その対策は、引き返すとか。そーいう事になるでしょう。

# 対策のコストを算出する
全ての対策には、コストが伴います。
傘を持っていくには、余分な手荷物というコストが発生します。日焼け止めは、購入コストが必要だし、余分な準備が対策のコストとなります。
コストと言っても、行動の話だと気持ちの部分でのコストとなり人によって大きさも違うかもしれませんが、それで構いません。重みは人によって変わるものです。
一方で、実際にコストが見えるものもあります。保険等は、明確にコストが見えるリスク対策となります。

# 最後に取捨選択する
対策コストが分かると、コストの大きさとリスクの確率から取捨選択を行います。

・　リスクが起きる確率xリスクが起きた時に被害額 < リスク対策コスト
→この状態は、対策コストが大きいので対策する必要がなさそうです。
・　リスクが起きる確率xリスクが起きた時に被害額 > リスク対策コスト
→この状態は、被害額の方が大きいので対策を打った方が得策です。

人は皆感情があるので、絶対に起きてほしくないリスクの場合は、重みをかけて調整したりするのも必要だと思います。又、リスクとリスクが連鎖する様なリスクも世の中には存在します。
その場合は、リスクの合計値で計算する必要もあります。

# いちばん大事な事
上記まででリスクに関しての考え方を整理してみました。
１．先ずは未来予想
２．次は確率を計算してみる
３．対策を考えてみる
４．対策のコストを算出する
５．最後に取捨選択する
人は普段、頭の中で無意識レベルでこの手順を繰り返してると思います。
研究では、人は、**一日で最大3万5,000回**の選択をしてるというデータもあります。
人の普段の選択では、自分の頭の中の感覚なので、無意識レベルで良いのですが、プロジェクト管理は、多数のステークホルダーを巻き込んだ選択をする必要があります。

## ２つ大事な話
１．未来は誰にも予測できない
　**ラプラスの悪魔**という言葉がありますが、人は未来を予測できると勘違いしがちです。
　100%大丈夫だろうと。自分はコントロール出来ていると。
　絶対にそんな事はありません。様々な変数が世の中には存在ます。
　誰もコロナでリモートワークになるとか予測する事は出来なかったと思います。
　**常にリスクが存在すると認識して下さい。**
２．リスクの確率とコストを共有する
　誰にも予測できません。リスクは時に発生します。しかし、全てのリスクに対応していてはコストが掛かって仕方ありません。更にはリスクを取らないリスクも存在します。
　そのため、全てのステークホルダーに**リスクの確率と対策コスト**を共有し、選択した理由を明確にします。
　明確になったリスクが発生したとしても、対策をしなかった理由が共有出来ていれば問題ありません。
　リスクが発生した時に問題となるのは、**リスクの確率と対策コスト、選択した理由**を共有していない時がほとんどです。

以上、プロジェクトマネジメントでのリスク管理の極意。参考にしてみて下さい。
【NVIDIA】NVIDIA cuda-samples使用方法

# はじめに
GitHubに書かれている手順がさっぱり・・・
見る人が見れば分かるのか???
そんな私、みなさんのためのメモです。

ですので新しい情報はないです。
GitHub見てください。
# 参考
- [GitHub cuda-samples (https://github.com/NVIDIA/cuda-samples)](https://github.com/NVIDIA/cuda-samples)
- [NVIDIA Architecture (https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/)](https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/)

# 環境
- OS　CentOS7.9 
- CUDA 11.2
- GPU V100

# 手順
- (1) cuda-samplesダウンロード
- (2) cuda-samplesビルド
- (3) 実行
- (4) 応用
# (1) cuda-samplesダウンロード
GitHubからcuda-samplesをダウンロード

https://github.com/NVIDIA/cuda-samples

```diff
- 緑色のコード⇒ダウンロードZIP
+ git clone https://github.com/NVIDIA/cuda-samples.git
```

# (2) cuda-samplesビルド
```bash:/tmp
# /tmpなどに保存して実行
tar zxvf cuda-samples-11.8.tar.gz
```

|Samples種類|概要|
|----| ---- |
|0.はじめに|初心者向けの基本的な CUDA サンプル|
|1.ユーティリティ|GPU/CPU 帯域幅を測定する方法|
|2. コンセプトとテクニック|CUDA 関連の概念と一般的な問題解決手法|
|3.CUDAの機能|CUDA 機能 (協調グループ、CUDA 並列処理など)|
|4. CUDA ゲートウェイ|CUDA プラットフォーム ゲートウェイ|
|5. ドメインの本質|ドメイン (グラフィックス、金融、画像処理) |
|6. パフォーマンス|パフォーマンスの最適化|

```bash:cuda-samples-11.8/Samples/bandwidthTest
# sampleディレクトリに移動
cd cuda-samples-11.8/Samples/

#今回はGPU運用監視に使用するのでbandwidthTestディレクトリに移動
cd bandwidthTest
make
>>>
    # エラー発生
    ~~~~~
    nvcc fatal   : Unknown option '-threads'
    ~~~~~
```

とりあえず同一ディレクトリの`Makefile`内の`-threads`削除(303行目)
```diff:cuda-samples-11.8/Samples/1_Utilities/bandwidthTest
vi Makefile
- ALL_CCFLAGS += --std=c++11
+ ALL_CCFLAGS += --threads 0 --std=c++11
```

再度実行
```bash:cuda-samples-11.8/Samples/1_Utilities/bandwidthTest
make
>>>
~~~
nvcc fatal   : Unsupported gpu architecture 'compute_75'
~~~
```

アーキテクチャが自動判別されており`compute_75`になっていました。
今回は`V100`を使用しているので`SMS="70"`を指定して再度実行

https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/

```bash:cuda-samples-11.8/Samples/1_Utilities/bandwidthTest
make SMS="70"
```

# (3) 実行
cuda-samples-11.8/bin/`x86_64`/linux/releaseに保存される
実行するOSによって変化。

```bash:cuda-samples-11.8/bin/x86_64/linux/release
cd cuda-samples-11.8/bin/x86_64/linux/release
./bandwidthTest
>>>
[CUDA Bandwidth Test] - Starting...
Running on...

 Device 0: Tesla V100-SXM2-32GB
 Quick Mode

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     12.4

 Device to Host Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     13.2

 Device to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     731.0

Result = PASS 
```

# (4) 応用

```bash
# ヘルプ表示
./bandwidthTest -help

# 全GPUに対して実行
./bandwidthTest --device=all

# host⇔device device⇔host device⇔device経路を変えて実行
./bandwidthTest --device=all [-htod | -dtoh | -dtod ]
```

ひとまず実行は出来ました。
Makefile内の一部削除しているので、強引です。
参考になれば

それではまた
Install MATLAB to Ubuntu20.04

# インストール手順

1.[MathWorks公式HP](https://jp.mathworks.com/downloads/web_downloads)よりLinux用をダウンロードする。

2.ターミナルを立ち上げ、以下の手順に沿ってインストールする(user@PC:~$省略)。

まず、zipファイルをダウンロードする。
```
cd ~/Downloads
mkdir matlabR2022bforunzip
mv ~/Downloads/matlab_R2022b_glnxa64.zip ~/Downloads/matlabR2022bforunzip
```
解凍する。
```
cd ~/matlabR2022bforunzip
unzip matlab_R2022b_glnxa64.zip
```
エラーが出ないようにする。
```
cd
sudo mkdir -p /usr/local/MATLAB/R2022b
sudo chmod 777 /usr/local/MATLAB/R2022b
sudo chmod 777 /usr/local/bin
xhost +SI:localuser:root
```
インストールする。すると、インストーラーが起動するので必要事項を入力する。
```
cd ~/Downloads/matlabR2022b/
./install
```
インストールが完了したらMATLABを起動する。
```
cd /usr/local/MATLAB/R2022b/bin/
./matlab
```
起動後、ターミナルにメッセージが現れるが、[バグレポート](https://jp.mathworks.com/support/bugreports/details/1995075)より、以下のメッセージは情報提供を目的としており、MATLAB には影響しない。
```
Gtk-Message: 12:34:56.789: Failed to load module "canberra-gtk-module"
```
以上。

---
<font color="yellowgreen">**QiitaLink**</font>
<font color="black">**Designed by RENOX**</font>
【React】UseEffectで取得した値をUseContextに渡す

### UseEffectで取得したデータをUseContextで共有する
useContextの記事を色々漁ってもハードコーディングした値をProviderやcreateContextに渡すような非現実的な例ばかりだったので備忘録。
アプリ起動時にuseEffectでデータを取得し、そのデータをコンテクストとしてアプリ内で共有したい場合を想定。
他にも方法はあるのかもしれないが、とりあえず動いた方法をメモ。

```react: App.jsx
import { useState, useEffect, createContext } from "react";
import axios from "axios";

export const DataContext = createContext(); //コンテクストオブジェクト準備

export default function App() {
    const [data, setData] = useState({}); //useContextに渡すデータ用のStateを用意
    
    useEffect(() => {
        async function fetchData(){
            try {
                const response = await axios.get(URL,{
                    headers: {
                        "Content-Type": CONTENT_TYPE,
                        "x-api-key": X_API_KEY
                    }
                });
                setData(response.data); //Stateをレスポンスで更新
            } catch (e) {
                //エラー処理
            }         
        };
        fetchData();
    }, [])
    
    return (
        <DataContext.Provider value={data}>
            //...Routerなどのコンポーネント
        </DataContext.Provider>
    )
}
```

```react: HomePage.jsx
import { useContext } from "react";

export default function HomePage() {
    const data = useContext(DataContext); //コンテクストのデータ取得

    //...その他の処理
}
```
useStateを使わずに変数（const dataなど）やuseRefにレスポンスを渡し、コンテクストのvalueにしようとするとHomePage.jsxのdataは空オブジェクトになる。

useEffectはレンダリング後に実行される関数なので、レスポンスが取得されたタイミングで再レンダリングをさせないとコンテクストのvalueが新しいものではなく、初期値の空データになってしまう。したがって再レンダリングを発生させるためにuseStateによるState管理を利用する。