OmniAICreator/Qiita-1.07M huggingface dataset:
Flutterで右左にスワイプできるカードリストを作成する

## はじめに
表題通り、カードリストを右左にスワイプできるようにする

## 成果物
![migi_hidari_swipe.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/b7346664-75d9-7722-c3a9-acbc1ffea99a.gif)


## ソースコード
```dart:lib/pages/home_screen.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../services/card_service.dart';
import '../models/card.dart' as CardModel; // 名前の衝突を避けるためにエイリアスを使用

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late CardService _cardService;

  @override
  void initState() {
    super.initState();
    _cardService =
        CardService(List<String>.generate(10, (index) => 'Card ${index + 1}'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
        actions: [
          IconButton(
            icon: Icon(Icons.location_on),
            onPressed: () {
              // NearbyPlacesScreenに遷移する
              context.go('/nearby');
            },
          ),
        ],
      ),
      body: Center(
        child: _cardService.cards.isNotEmpty
            ? Dismissible(
                key: UniqueKey(), // 各 Dismissible に一意のキーを与える
                direction: DismissDirection.horizontal,
                onDismissed: (direction) {
                  setState(() {
                    if (direction == DismissDirection.startToEnd) {
                      _cardService.swipeRight();
                    } else if (direction == DismissDirection.endToStart) {
                      _cardService.swipeLeft();
                    }
                  });
                },
                child: Card(
                  child: ListTile(
                    title: Text(_cardService.currentCard.title),
                  ),
                ),
              )
            : Text('No more cards'),
      ),
    );
  }
}
```

```dart:lib/models/card.dart
class Card {
  final String title;

  Card(this.title);
}
```

```dart:lib/services/card_service.dart
import '../models/card.dart';

class CardService {
  final List<Card> _cards;
  int _currentIndex = 0;

  CardService(List<String> titles)
      : _cards = titles.map((title) => Card(title)).toList();

  List<Card> get cards => _cards;

  int get currentIndex => _currentIndex;

  Card get currentCard => _cards[_currentIndex];

  void swipeRight() {
    if (_currentIndex < _cards.length - 1) {
      _currentIndex++;
    } else {
      _currentIndex = 0; // 最後のカードから最初のカードに戻る
    }
  }

  void swipeLeft() {
    if (_currentIndex > 0) {
      _currentIndex--;
    } else {
      _currentIndex = _cards.length - 1;
    }
  }
}
```
リモートワークでやる気が出ないときの対策

あくまで個人的な対策です

## 朝はまず散歩をする

朝はまず布団から出るのに苦労しますついつい布団の中でスマホを見始めてしまうとそこで1日が終了してしまう

そうならないために朝起きてすぐ布団から出られるように対策を取りたい

リモートワークだと自宅での作業のため布団から出るとすぐに机に向かって仕事をすることができる仕事とプライベートの切り替えがしっかり行える人だと問題にはならないが、自分の場合はスイッチングコストが掛かるので、布団から出る=仕事するとなってしまうと布団から出ることが億劫になり、ついつい二度寝をしてしまう

対策として、朝起きたらすぐに散歩をするようにした普段人と全く会わないからか、家の近くを散歩するのはとても楽しい

「朝起きたら散歩がしたい」と思うようになったので、布団でだらだら過ごすことが少なくなったし、散歩をしていると仕事のことを考えるので「帰ったらこれをやろう」と一日のTODOが散歩中に決まる

## 待ち時間にSNSを見ない

ビルド中やレビュー待ちの時間はどうしても発生しますこのタイミングで「ひと休憩」とスマホでブログの記事やSNSを見てしまうと仕事モードから休憩モードに切り替わってしまい、再度仕事モードに戻すのに意志の力が必要になってしまう

意志は自分の中で坂道のような感覚やればやるほどどんどん加速していくので、集中を切らさずにやり切ることが大切だと感じる

世の中にはポモドーロ・テクニックのような手法があるが、過集中になる自分にはあまり向いていない気がする

## タスクを進める気にならないとき

**簡単なことから始める**

複雑なタスクだとタスクの内容を理解するだけで時間がかかるため、始めるのが億劫になる

やる気は行動することで発生するので、

- ブランチを切る
- notionに最初にやる最小限のことを書く
- 修正箇所に該当しそうなコードを探す

くらいの簡単なことをまず始める

コードを読んでいたら気づいたらタスクを行っていて、1日が終わることも珍しくないタスクを進めているときは時間が気にならないので、まずは始めてみるということが何よりも大切

## 余計なことを考えない

このままで大丈夫かな？

将来が不安だ

このPRの内容で間違っていないか？

など、考えても時間が溶けてしまうだけのことは考えないようにする

考えすぎないほうが幸福度が高いし、行動こそが何よりの正義

悩むと考えることは異なるものだという認識を持つこと

結論が出ることはちゃんと考える結論が出ないことを考えているときは悩んでいるとき→これは考えても無駄だと割り切る

## 人とコミュニケーションを取る

リモートワークでもslackなど社内ツールがあったりするので、そこでつぶやく

人とコミュニケーションを取ることで「やらないと」という強制力が働いたり、やる気が出るので「おはようございます」とか「業務開始」などのつぶやきだけでも行うと良い

## 最後に

他にも「自分はこうしてます！」みたいな考えがあれば募集してます！
EC2（Debian）インスタンスにReazonSpeech v2をインストールする手順　

# はじめに

こちらの記事は「[EC2（AmazonLinux2023）インスタンスにReazonSpeech v2をインストールする手順](https://qiita.com/ai_imatch/items/4702fc92f33355c77efb)」の「Debian」版です！
詳しくはそちらの記事をご参照ください。
では早速、はじめていきましょう！

### 使用技術

文字起こし：reazonspeech-nemo-v2

実行環境サーバー：AWS EC2(Debian)


### 前提条件
・HuggingFaceのアカウントが取得済みであること

# 目次

1.事前準備

2.環境構築

3.ソースのデプロイ

4.コード実行

5.まとめ

それでは、実際の環境構築に進んでいきましょう！

# 1.事前準備

## 利用モデルの利用規約を許諾する

- 「[reazon-research/reazonspeech](https://huggingface.co/datasets/reazon-research/reazonspeech)」のページへアクセスし、ユーザー利用条件の受け入れ（Accept）を実施
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3831490/874c84d3-0384-b2a9-73cc-2c3bfb29c1c1.png)

# 2.環境構築

## EC2インスタンスの起動
- AWSコンソールから「EC2」サービスへアクセス
- 下図を参考にインスタンス起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3831490/aca853db-c566-b729-4420-c7d64e13b565.png)


- AMI:「Debian 12(HVM), SSD Volume Type」を選択
- インスタンスタイプ：t2.large(メモリ8GBほしいので)
- ボリューム：70GiB(諸々のインストールで結構容量食う)

### 作成したインスタンスを選択し「インスタンスを開始」

SSHクライアントからインスタンスへ接続し下記のコマンドを実行

```
# aptのアップグレード
sudo apt update
sudo apt upgrade

# python関連およびgitのインストール
sudo apt install python3
sudo apt install python3-pip
sudo apt install python3.11-venv
sudo apt install git
```

```
# Pythonのvenv環境作成
python3 -m venv venv
source venv/bin/activate

# Cythonをインストール
pip install Cython

# 依存関係のあるパッケージのインストール
pip install numpy==1.23.5
pip install huggingface_hub==0.23.2
pip install nemo_toolkit
```

```
# ReazonSpeechをインストール
cd /tmp
git clone https://github.com/reazon-research/ReazonSpeech
pip install ReazonSpeech/pkg/nemo-asr
```

## ソースのデプロイ
### 「app.py」ファイルを任意のディレクトリにデプロイする

```python:app.py
from reazonspeech.nemo.asr import load_model, transcribe, audio_from_path

# 実行時にHugging Faceからモデルを取得します (2.3GB)
model = load_model(device='cpu')

# ローカルの音声ファイルを読み込む
audio = audio_from_path('test.wav')

# 音声認識を適用する
ret = transcribe(model, audio)

print(ret.text)
```
※「音声ファイル（test.wav）」は別途用意し、app.pyと同一のディレクトリにおいてください。

# 4.コード実行

デプロイしたディレクトリに移動して、app.pyの実行
```bash:command
python app.py
```

音声ファイルの文字起こし結果が、標準出力されたら成功です。

# 5.まとめ

今回はEC2インスタンスに音声認識モデル「ReazonSpeech v2(nemo)」をインストールして、実際に文字起こしを行うという手順でした。
パッケージの依存関係で数日ハマりましたが、何とか動作するパターンを見つけました。

改めて下記にまとめます。
```
numpy==1.23.5
huggingface_hub==0.23.2
nemo_toolkit
```

それではまた別の記事でお目にかかります。
ありがとうございました。

# 6.参考記事

[参考サイト] 
https://research.reazon.jp/projects/ReazonSpeech/howto.html#python
https://github.com/NVIDIA/NeMo/issues/9793
【TypeScript×React】型指定をする時、何の型にすればいいか分からなくなった時の自分流Tips

# はじめに
TypeScriptの初心者の方は掲題のような状況には心当たりありませんか？（私はめっちゃあります）
そんなときの自分流のTipsを展開します！

# 問題
TypeScriptで、引数定義等をする際に、これ何の型を指定するんだっけ？という時の自分なりの解決方法です。
例えば、↓の部分で言う「この部分」のところに何を指定するんだっけ？という場合

```diff_tsx:Sample.tsx
import { FC } from "react";

export const Sample: FC = () => {
+ const onChangeName = (e: 「この部分」) => {};

  return (
    <form>
      <input type="text" name="name" onChange={onChangeName} />
    </form>
  );
};
```

# 解決方法
まず、「この部分」のところに適当な型を入れます(↓では「string」を入れる)。

```diff_tsx:Sample.tsx
import { FC } from "react";

export const Sample: FC = () => {
+ const onChangeName = (e: string) => {};

  return (
    <form>
      <input type="text" name="name" onChange={onChangeName} />
    </form>
  );
};
```

そうすると、当然VSCode上でエラーになるので、エラーとなっているinput項目上のonChangeの部分でマウスをホバーします。

![スクリーンショット 2024-08-08 20.05.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832049/b72ae744-ba5a-ebdc-ffb6-6050ec72337d.png)

すると↑のようなエラーが出ますが、4行目に「型 'ChangeEvent<HTMLInputElement>' を型 'string' に割り当てることはできません。ts(2322)」が出ています。
ここで正しい型を表示してくれているので、ChangeEvent〜の部分をコピーしてstringの部分にそのまま貼り付けて、import文を追加します。

```diff_tsx:Sample.tsx
import { ChangeEvent, FC } from "react";

export const Sample: FC = () => {
  const onChangeName = (e: ChangeEvent<HTMLInputElement>) => {};

  return (
    <form>
      <input type="text" name="name" onChange={onChangeName} />
    </form>
  );
};
```
するとエラーが消えます！便利！！

# おわりに
まあ慣れればいちいちこんなことしなくてもいいんでしょうけど^^;

## JISOUのメンバー募集中🔥
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！👇

https://projisou.jp/
rustdesk を Linux で使ってみる

Windows PC のリモートサポートでは NTT 東日本 - IPA の「シン・テレワークシステム」を使っているのだが、 Linux をリモートサポートするには何がいいかな?

NAT越えができて、中継サーバなどを設置しなくても良いものとして、 rustdesk を試してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/86b142b9-6c5e-f0f3-f549-cd950868c62a.png)

# 環境

- 接続元 Ubuntu 22.04 LTS
- 接続先 openSUSE Tumbleweed KDE フレーバー

# ダウンロード

https://rustdesk.com/ からダウンロードボタンを押す。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/46266328-44dc-640d-2cfc-0f38a52dcc64.png)

ここからダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f2781587-13d0-f91b-0ef7-0a688f140537.png)


# インストール

接続元も、接続先も単一のアプリで動かします。

## Ubuntu でのインストール

x86-64(64bit) の Ubuntu を押すと、deb ファイルがダウンロードされます。


```
$ sudo apt-get install curl libxdo3
$ sudo dpkg -i rustdesk-1.2.7-x86_64.deb 
```

## openSUSE

x86-64(64bit) の Flatpak をダウンロードしました。

openSUSE に flatpak をインストールしようとしたら既に入っていました。


```
> sudo zypper install flatpak
リポジトリのデータを読み込んでいます...
インストール済みのパッケージを読み込んでいます...
'flatpak' は既にインストール済みです。
'flatpak-1.15.8-3.1.x86_64' に対する更新候補はありません。既に最新のバージョンがインストールされています。
パッケージの依存関係を解決しています...
何もすることがありません。
```

flatpak からインストールします。
```
> sudo flatpak install rustdesk-1.2.7-x86_64.flatpak
```

# 実行


双方で rustdesk を起動して、接続先のID,パスワードを接続元から入力して接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/86b142b9-6c5e-f0f3-f549-cd950868c62a.png)
接続できました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7186a322-ede4-f522-25c4-80a942292e3b.png)


# 所感
- rustdesk で検索すると、中継サーバをインストールする記事が割と出てきて、中継サーバが必須かと思いましたがそんなことはありませんでした。
パフォーマンスは自分でサーバを建てるのが良さそうですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/12f5fe3e-6ff8-5f11-5082-eca2a8dcba17.png)

- また、 Wayland の警告が出てますが、サポート先ユーザがデスクトップからアプリを起動するやりかただと特に問題はありませんでした。

- 日本語変換は問題なくできました。
 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/21fe4b5a-bfc0-3943-db0e-9e2762e2fcf8.png)

以下は NTT 東日本 - IPA の「シン・テレワークシステム」と比べての感想です。
- リモートで表示する解像度は接続先物理ディスプレイのサイズとなります。
- 操作中の画面は接続先のローカルディスプレイでも同様に表示されます。
- 結構圧縮ノイズが入ります。
- Chat機能とかがあるので活用できそう。
- ユーザーに rustdesk アプリを起動してもらって、リモートから接続するという運用になりそう。
TypeScriptの配列の[]の型定義とジェネリクス型の書き方(2次元配列など)

## アジェンダ
TypeScriptでは、配列の型を定義する方法として主に2つの方法があります。
型の後ろに `[]` を付ける方法とジェネリック型 `Array<T>`を使う方法とです。
どちらの方法も同じ意味を持ちますが、書き方が異なります。ここでは、これらの方法の詳細とそれぞれの特徴について説明します。

## 配列の型定義方法
### 方法1: 型の後ろに `[]` を付ける方法

この方法では、型の後ろに `[]` を付けることで配列の型を定義します。例えば、数値の配列を定義する場合は以下のようになります。

```typescript
let arr2: number[] = [0, 1, 2];
```

### 方法2: ジェネリック型 `Array<T>` を使う方法

この方法では、配列の型を `Array<number>` のようにジェネリック型を使用して定義します。例えば、数値の配列を定義する場合は以下のようになります。

```typescript
let arr1: Array<number> = [0, 1, 2];
```

## 二次元配列の型定義

同様の方法で、二重配列も定義できます。
### 方法1: 型の後ろに `[]` を付ける方法

```typescript
let matrix2: number[][] = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8]
];
```

### 方法2: ジェネリック型 `Array<T>` を使う方法
ジェネリクス型の二重配列の記述の仕方は2パターンあります。

#### `Array<Array<number>>` の使用
```typescript
let matrix1: Array<Array<number>> = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8]
];
```

#### `Array<number[]>` の使用
```typescript
let matrix2: Array<number[]> = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8]
];
```

## どちらの方法を選ぶべきか？

実際のところ、どちらの方法を使用しても機能的には同じです。選択は主にコードの可読性やチームのコーディングスタイルによります。

- **`T[]` の使用:** よりシンプルで読みやすい表記を好む場合や、JavaScriptの配列表記に慣れている場合に適しています。
- **`Array<T>` の使用:** より一般的なジェネリック型の表記を使用する場合や、より明確に意図を示したい場合に適しています。

## まとめ
TypeScriptで配列の型を定義する方法には、ジェネリック型 `Array<T>` を使う方法と型の後ろに `[]` を付ける方法の2つがありますが、どちらの方法を使用しても機能的には同じですが、コードの可読性やチームのコーディングスタイルに応じて選択することが良いと思います。
robot作成日記

raspberrypi4Bを使ってrobotの顔を作る

#1日目
raspberrypi cameraのv2を繋げ、openCVを使って顔認証をしたい。

raspberrypi4bの64bit版のインターフェイス設定にcameraがないのでhttps://note.com/kiyo_ai_note/n/nddaa85727c1d
↑のnoteを参考にセットアップする
注意：最初にcameraが0:0:0で反応しなくてもsudo raspi-configでカメラモジュールを有効にし、rebootした後に１、１になるので大丈夫。
”/boot/config.txt”内のcamera configurationを修正する際にV２はdtoverlay=imx219なんでそれを追加する。
cameraできた。
次に顔認証
https://qiita.com/mnishiguchi/items/3ef4a1d4f8a56a995b88
なんかnumpyとopencvのversionが違うみたいでエラーが出る。謎
https://www.youtube.com/watch?v=9P-Hq8Dh1R0
この動画のやつを試してみる。
youtubeのやつ長いから今日はそれで終わり
試したら相変わらずnumpyとのバージョンが合わへんって言われる　ど湯こと
エラー対応Sandbox: bash(4218) deny(1) file-write-create ....



下記エラー対応

Sandbox: bash(4218) deny(1) file-write-create /Users/admin/Documents/GitHub/xxx/Pods/resources-to-copy-xxx.txt

ENABLE_USER_SCRIPT_SANDBOXING　を　No

![スクリーンショット 2024-08-08 19.05.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244853/858d8b56-0186-be15-ea89-d3d6cf42552d.png)![uploading...0]()


引用元
https://zenn.dev/feb19/articles/c3e6ec545383bb
VSCodeエディタ内でprettierが動かなくなった

多分近い将来不要になる記事

保存時にprettierが動くようにしてあったのが、VSCodeバージョンアップのせいなのか動かなくなった
バージョンは以下の通り
```
バージョン: 1.92.0 (user setup)
コミット: b1c0a14de1414fcdaa400695b4db1c0799bc3124
日付: 2024-07-31T23:26:45.634Z
Electron: 30.1.2
ElectronBuildId: 9870757
Chromium: 124.0.6367.243
Node.js: 20.14.0
V8: 12.4.254.20-electron.0
OS: Windows_NT x64 10.0.22621
```

エラーメッセージは以下の通り
```
["ERROR" - 18:50:43] Error formatting document.
["ERROR" - 18:50:43] spawn EINVAL
Error: spawn EINVAL
    at ChildProcess.spawn (node:internal/child_process:421:11)
    at Object.spawn (node:child_process:799:9)
    at file:///c:/XXX/node_modules/prettier-plugin-apex/dist/src/parser.js:19:38
    at new Promise (<anonymous>)
    以下略
````

ネットで以下の記事を見つけたので
https://github.com/prettier/prettier-vscode/issues/3468
それに従って以下対応した

エラーメッセージに出ている c:/XXX/node_modules/prettier-plugin-apex/dist/src/parser.js の19行目を以下のように変更し、VSCodeを再起動したら治った

前：`const process = childProcess.spawn(serializerBin, args);`
後：`const process = childProcess.spawn(serializerBin, args, { shell: true });`

以上
パーフェクトRubyonRails備忘録1

# find,find_by,whereの戻り値の違い

- find
    - ActiveRecord::RecordNotFound例外
- find_by
    - nil
- where
    - 空のActiveRecord::Relationインスタンス

# ActiveRecord::Relationについて

- ActiveRecord（モデル）に対してQueryInterface（select,where,etc）が呼ばれることでActiveRecord::Relationのインスタンスが作成される
- ActiveRecord::Relationインスタンスに対してQueryInterfaceを繰り返し呼び出せる
- 実際にデータが必要になった時点でSQLが発行され、それまではActiveRecord::RelationにSQLの情報が蓄積される。
- ただし、 `to_a`メソッドにより、明示的にSQLを発行することもできる。

# scopeについて

- スコープとは？
    - よく使う検索条件に名前をつけて再利用しやすくする仕組み
- スコープの戻り値
    - 必ずActiveRecord::Relationを返す
    - なので、scope定義でfind_by（nilを返す）を使うと、一件も取得できない時に、find_byの条件を無視して、全件取得してきちゃう。
    - **なので！、**scope定義ではfind_byは使わない方がいい（合ってますか？）
    - 参考→[【Rails】スコープでfind_byを使用して、条件に一致するレコードがないとnilではなくレコード全件が返される理由 #Ruby - Qiita](https://qiita.com/kaito_program/items/435a9fc3930779998f4d)

# モデル間のリレーションについて

- リレーション作成の流れ
    - 条件
        - 1対多（Group（多）、Member（1））
    1. Memberに外部キーを追加する
        
        ```bash
        rails generate migration AddGroupIdToMembers group:references
        ```
        
        これにより、membersテーブルに、group_idが追加される
        
    2. Group、Memberモデルに関連を宣言する
        
        ```ruby
        class Group < ApplicationRecord
          has_many :member
        end
        
        class Member < ApplicationRecord
          belongs_to :groups
        end
        ```
        

# ActiveRecord::Enumについて

- ActiveRecord::Enumとは？
    - ステータスを管理するカラム（例：値が、0, 1, 2に限られる）をRailsで扱いやすくするために、対応した名称でアクセスできるようにしてくれる機能
- 例
    - Todoモデルのステータス（0：waiting、1：working、2：completed）を名前で管理、更新する
    
    ```ruby
    class Todo < ApplicationRecord
      enum todo_status: {
        waiting: 0,
        working: 1,
        completed: 2,
      }
      # 略
    end
    ```
    
    こうすることで、Todoの更新、作成の時に名称（文字列orシンボル）もしくは数値で指定できる。
    
    ```ruby
    Todo.create(todo_status: "waiting")
    Todo.create(todo_status: :waiting)
    Todo.create(todo_status: 0)
    # 全て同じ結果になる。
    ```
    
    また、述語メソッドで問い合わせも可能になる。
    
    ```ruby
    todo = Todo.first
    todo.waiting? # false
    todo.waiting! # 変更できる
    todo.waiting? # true
    ```
    
    ステータスの一覧（名称と実際の値のハッシュ）や、実際の値にアクセスできる
    
    ```ruby
    Todo.todo_statuses
    # => {"waiting"=>0, "working"=>1, "completed"=>2}
    todo.todo_status_before_type_cast
    # => 0
    ```
    
    スコープも追加される
    
    ```ruby
    Book.waiting
    # => ステータスがwaitingのものを検索
    Book.not_waiting
    # => ステータスがwaitingでないものを検索
    ```
Pythonを使ってPDF文書の注釈を簡単に削除する方法

PDF文書は、そのプラットフォーム間の互換性とフォーマットの安定性から広く利用されています。しかし、文書が異なるユーザー間で共有されるにつれて、蓄積された注釈が雑然とし、場合によっては機密情報や古い情報を含むこともあります。これにより、文書の明確さやプロフェッショナリズムが損なわれるだけでなく、プライバシーリスクを引き起こす可能性もあります。そのため、最終版を公開したり、外部のパートナーと文書を共有したりする前に、PDF文書から不要な注釈を削除することは非常に重要です。Pythonの強力な機能を活用することで、このプロセスを自動化し、文書をクリーンかつ安全に保つことができます。
この記事では、**Pythonを使用してPDF文書の注釈を削除する方法**を解説します。

- **[PythonでPDFの特定のページから特定の注釈を削除](#pythonでpdfの特定のページから特定の注釈を削除)**
- **[PythonでPDF文書内のすべての注釈を削除](#pythonでpdf文書内のすべての注釈を削除)**

この記事で紹介する方法には、[Spire.PDF for Python](https://jp.e-iceblue.com/download/spire-pdf-for-python.html)が必要です。PyPIからインストールできます：`pip install Spire.PDF`。

[無料ライセンスの申請](https://www.e-iceblue.com/TemLicense.html)

## PythonでPDFの特定のページから特定の注釈を削除
`PdfDocument.LoadFromFile()`メソッドを使用してPDF文書を読み込んだ後、`PdfDocument.Pages.get_Item()`メソッドを使って指定したページを取得し、`PdfPageBase.AnnotationsWidget.RemoveAt()`メソッドで特定の注釈を削除することができます。
以下は詳細な手順です：
1. 必要なモジュール`PdfDocument`をインポートします。
2. `PdfDocument`のインスタンスを作成します。
3. `PdfDocument.LoadFromFile()`を使用してPDF文書を読み込みます。
4. `PdfDocument.Pages.get_Item()`を使用して特定のページを取得します。
5. `PdfPageBase.AnnotationsWidget.RemoveAt()`メソッドを使用して特定の注釈を削除します。
6. `PdfDocument.SaveToFile()`メソッドでPDF文書を保存します。
7. リソースを解放します。

**コード例**
```python
from spire.pdf import PdfDocument

# PdfDocumentインスタンスを作成
pdf = PdfDocument()

# PDFドキュメントを読み込む
pdf.LoadFromFile("Sample.pdf")

# 指定ページを取得
page = pdf.Pages.get_Item(0)

# 指定した注釈を削除
page.AnnotationsWidget.RemoveAt(0)

# ドキュメントを保存
pdf.SaveToFile("output/指定されたPDF注釈を削除.pdf")
pdf.Close()
```

結果
![PythonでPDFの特定のページから特定の注釈を削除](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/a5b5e67d-7f28-8945-539e-95a5538d8687.png)

## PythonでPDF文書内のすべての注釈を削除
同様の手法で、PDF文書内のすべての注釈を削除することも可能です。文書内のすべてのページをループし、`PdfPageBase.AnnotationsWidget.Clear()`メソッドを使用してそのページのすべての注釈を削除します。
以下は詳細な手順です：
1. 必要なモジュール`PdfDocument`をインポートします。
2. `PdfDocument`のインスタンスを作成します。
3. `PdfDocument.LoadFromFile()`を使用してPDF文書を読み込みます。
4. 文書内の各ページをループして：
   - `PdfDocument.Pages.get_Item()`を使用して現在のページを取得します。
   - `PdfPageBase.AnnotationsWidget.Clear()`メソッドを使用してそのページのすべての注釈を削除します。
5. `PdfDocument.SaveToFile()`メソッドでPDF文書を保存します。
6. リソースを解放します。

**コード例**
```python
from spire.pdf import PdfDocument

# PdfDocumentインスタンスを作成
pdf = PdfDocument()

# PDFドキュメントを読み込む
pdf.LoadFromFile("Sample.pdf")

# PDF内のすべてのページをループ
for i in range(pdf.Pages.Count):
    # 現在のページを取得
    page = pdf.Pages.get_Item(i)
    # 現在のページのすべての注釈を削除
    page.AnnotationsWidget.Clear()

# ドキュメントを保存
pdf.SaveToFile("output/すべてのPDF注釈を削除.pdf")
pdf.Close()
```

結果
![PythonでPDF文書内のすべての注釈を削除](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/7be3edc4-f581-6bc7-10d1-e7bfd2bb9c26.png)

この記事では、Pythonコードを使用してPDF文書内の注釈を簡単に削除する方法を解説しました。

さらに詳しいPDF文書の処理方法については、[Spire.PDF for Pythonのチュートリアル](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Spire.PDF-for-Python-Program-Guide-Content.html)をご覧ください。
DjangoをVSCodeで１行ずつデバックする方法

## はじめに
Djangoで開発をしていて、１行ずつデバックしたいのになかなか実現できなかったため、その原因と対処法を記載していきます。

## 参考にした記事
[VSCodeでDjangoのアプリをデバッグ実行する](https://qiita.com/mei2678/items/c126054b804d9274cd12)

## 結論
基本、参考にした記事の通りに行えば、実現できます。
しかし、この記事の中で見落としていた箇所があり、私の場合時間がかかってしまいました。

### 見落としていた箇所
**ディレクトリ構成**です！
私の場合のディレクトリは以下のようになっていました。
```
system名
├──venv
├──django-project
│    ├──project
│    │    ├── config
│    │    ├── __init__.py
│    │    ├── asgi.py
│    │    ├── settings.py
│    │    ├── urls.py
│    │    ├── wsgi.py
│    │    └── __pychache__
│    └── 各アプリケーション
└──vue-project
```
この状態で参考記事通りに進めても、うまく行きません。
後述するlaunch.jsonで、各ディレクトリのパスを指定する必要があるため、自身のvディレクトリ構成がどのようになっているか確認しておきましょう。

## launch.jsonの作成位置
私の場合、launch.jsonを作成する箇所は以下の通りでした。
※launch.jsonをどのように作成するかは、参考にした記事をご参照ください。
```
system名
├──venv
├──.vscode
│    └── launch.json #←ここ！！
├──django-project
│    ├──project
│    │    ├── config
│    │    ├── __init__.py
│    │    ├── asgi.py
│    │    ├── settings.py
│    │    ├── urls.py
│    │    ├── wsgi.py
│    │    └── __pychache__
│    └── 各アプリケーション
└──vue-project
```
参考記事との違いは、django-project内に作成しているか、していないか、です。
私の場合は、django-projectディレクトリの外に作成する必要がありました。

## launch.jsonの作成位置が重要な理由
前述に少し記載しましたが、launch.jsonの設定の中で、ディレクトリのパスを指定する必要があるためです。

```
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: Django",
              "type": "debugpy",
              "request": "launch",
              "args": [
                "runserver"
              ],
              "django": true,
              "autoStartBrowser": false,
            "program": "${workspaceFolder}/django-project/manage.py", -- ①
            "env": {
                    "PYTHONPATH": "${workspaceFolder}/venv/lib/python3.x/site-packages", -- ②
                    "VIRTUAL_ENV": "${workspaceFolder}/venv",
                    "PATH": "${workspaceFolder}/venv/bin:${env:PATH}",
                    "DJANGO_SETTINGS_MODULE": "project.settings.local",
            }
        }
    ]
}

```
### ①manage.pyのパスの指定
"program"キーに対する値は、manage.pyのパスを指定する必要があります。
${workspaceFolder}は、私のディレクトリ構成でいうsystem名です。

### ②venvのパスの指定
"env"オブジェクトの中で定義しているものについては、以下の通りです。
- PYTHONPATH: Pythonがモジュールを検索するパスを指定
- VIRTUAL_ENV: 仮想環境のパスを指定
- PATH: 実行可能ファイルを検索するパスを指定

## まとめ
以上のようにディレクトリ構成と、指定するパスに気をつけてみると、できました！
基本中の基本を見落としていたため、今後気をつけて行こうと思います。
HuggingFaceを勉強し初めたばかりだけどHuggingFaceについて人前でしゃべったお話

# きっかけ
Transformerのモデル構造についてもう一度学習しようと思って、Xでポストしたんです。O'reillyの「機械学習エンジニアのためのTransformers」の写真を付けてね。

https://x.com/ikedachin/status/1791812763582644574


### この本の本家githubはこちら。

https://github.com/nlp-with-transformers

### 日本サイトはこちら
https://github.com/oreilly-japan/nlp-with-transformers-ja


そしたら、それを見ていたマナビDXクエスト アルムナイを立ち上げた某氏から、
「**アルムナイイベントでHuggingFaceについて話して～！（ビールを注ぎながら）**」
と頼まれたのがきっかけ（ちょっと意訳有り）。

とは言え、使い始めたのは頼まれた日の約一月前の初心者。さて、どうなることやら。

### マナビDXクエストについて
https://dxq.manabi-dx.ipa.go.jp


# アジェンダ作成
お世話になっている方からのお話だったので準備開始。
というわけで、最初は半分イヤイヤ・・・と思いきや、結構アゲアゲでノリノリになってきましたよ。

私自身も初心者なので、モデルをダウンロードして使えるってところまでと決めて、アジェンダをGPT-4に作ってもらう。笑


1. 自己紹介
1. 勉強会の目的
1. Hugging Faceを使おうと思ったわけ • Hugging Faceとは
1. Hugging Faceサイトの構成と見方
1. デモンストレーション
1. デモンストレーションの前に
1. Google Colabで使ってみる
1. UseCaseを考えてみよう
1. まとめ

ということで準備期間は３週間。
使える時間は昼休みと仕事終わりの1時間/日（毎日ではない）です。

# 準備開始してから発覚

- あれ？自分が思っている以上にわかってないじゃん
- 他のモデルも使えるやろ・・・えっ
- tokenizerの使い方・・・汗

そう、「機械学習エンジニアのためのTransformers」を読み進めながら写経しているだけではなんもわかってなかったんっすよ。イヤイヤ、そもそも本の読み方から反省ですね。
なので、デモンストレーション用のソースコード作り、想定質問への対応も想定しながらなので、全作業の約7割はここに当てました。

そして思った。
**もう一周、勉強し直さないとイケねぇ・・・**

# 欲張る
そう、準備すればするほど欲が出るもの。
その欲張る「幅」を「HuggingFaceを使うと*特に嬉しいこと*」とした。
- 最近のモデルを触ってもらう
- 特に今回感じていた`datasets`ライブラリの素晴らしさを体験してもらう

最近のモデルで、比較的多くの人のパソコンで動いてくれるモデルを**ローカル**で動かすと嬉しくないですか？
僕は嬉しい。


ということで、軽量モデルとして出たPhi-1を選択。
が、いざ出力するとイマイチだったので、Phi-1.5を最終的に選択

また、`datasets`については、この三つについて紹介することにした。
- ファイルの抜き取り
- map関数
- ストリーミング

いや、モリモリ過ぎだろ。w


# 家庭内リハーサルと本番
zoomだけど数十名の前で話すわけだからちゃんとリハーサルはしました。
HuggingFaceを全く知らない家族に協力してもらいました。

が、本番はというと「テンパってしまった」です。
人前に出るとアゲアゲになる（意味違う）癖が出ちゃいましたね。
早口になっちゃいましたし、あわあわとしてしまった。

しかし、同じようにHuggingFaceを活用したいという仲間も多く、隔週で「モクモク会」をやることになりました。これは嬉しい誤算。

8/4（日）にすでに第一回モクモク会が無事に開催され、様々な人と話し合いができたのが嬉しかったです。今は「機械学習エンジニアのためのTransformers」の２週目に入っていて、次回モクモク会に向けてオリジナルのデータセットを作ってみたり、日本語モデルを使ってみたりとチャレンジしてます。


マナビDXクエストアルムナイに参加されている方はどなたでも参加できますので声かけてくださいね。



# GitHub
並行してGitHubの使い方も勉強中
これ、ほんと便利っすね。
ということで、当日の資料やらこちらに保存してますのでお好きに閲覧してってください。
次回ネタも含んじゃってますけどね。w

https://github.com/ikedachin/study_huggingface/tree/main/1st_introduction


# 振り返り

お世話になっている方からのお願い/お誘いを受け入れたことで世界が広がりました。
いいっすね。こういうの。
マナビDXクエストで知り合って仲間になれた。その人のお誘い・お願いがきっかけで偉大な最初に一歩を踏み出すことができました。

おかげで、人前で話す練習というか、経験を踏まなきゃと思ったり、やりたいこと、言いたいことが増えてきました。

ちなみに、こんなイベントのお手伝いもすることになりました。（詳細はもうちょい待って！）
実は前回は単なる一参加者でしたが、すごい人たちが名古屋にもいるなぁと思って思い切って運営に飛び込んでみました。
すごい人たちなんで、僕なんかがやれることは受付くらいのもんですが、ここで将来登壇できるように頑張ろう。うん。


https://kinto-technologies.connpass.com/event/325725/

ほんと、きっかけをくれたK.Mさん、ありがとん！
ほんじゃまた。
ベストなWindowsへのMakeのインストール方法は？

## まとめ
この記事では[Chocolatery](https://chocolatey.org/)によるインストールが最適との結論に至りました。
Chocolateryがインストールされていない場合はPowerShellを管理者権限で開き次のコマンドを実行するとインストールできます（[参考](https://chocolatey.org/install#individual)）。
```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```
続いてMakeで次のコマンドでMakeをインストールできます。
```powershell
choco install make
```

## どんな方法があるのか
WindowsにMakeをインストールするには次の方法があります。
1. [MinGW-w64](https://www.mingw-w64.org/)
1. [Chocolatey](https://community.chocolatey.org/packages/make)
1. [Winget](https://winget.run/pkg/GnuWin32/Make)
1. [WSL](https://learn.microsoft.com/ja-jp/windows/wsl/install)

**MinGW-w64**
MinGW-w64はWindows上で動作するGNUコンパイラコレクション（GCC）を提供するプロジェクトです。
[ダウンロードページ](https://www.mingw-w64.org/downloads/)を見ると分かるようにたくさんのダウンロード方法があり、[MSYS2](https://www.msys2.org/)経由や[GitHub](https://github.com/niXman/mingw-builds-binaries)経由のダウンロードが楽かと思います。
ただ、いずれにしろ次以降に紹介する方法と比べてインストールが煩雑なので一番のオススメにはしませんでした。

**Chocolatey**
[Chocolatey](https://community.chocolatey.org/)はWindows用のパッケージマネージャです。
Ubuntuでいうところのapt、Pythonでいうところのpip的な役割を果たしてくれます。
Chocolatery自体のインストールも簡単でChocolatery経由のMakeのインストールも簡単なので一番オススメです。
それと、[Make公式サイトのマニュアル](https://www.gnu.org/software/make/manual/make.html)から確認できる最新バージョン（執筆時点では4.4.1）を[ChocolateyのMake](https://community.chocolatey.org/packages/make)のバージョン（執筆時点では4.4.1）がしっかりと追従しているのがいいですね。

**Winget**
[Winget](https://winget.run/)はMicrosoftオススメのパッケージマネージャなので信頼できそうなんですが、いかんせん[WingetのMake](https://winget.run/pkg/GnuWin32/Make)のバージョンは執筆時点で3.81と本家のバージョンを追従できていないのでChocolateyの方がおススメです。

**WSL**
WSLはWindows上にLinuxをセットアップできる一番簡単な方法だと思います。
WSLによるMakeのインストールもすごくオススメですが、WSLってすごく容量食いますよね…
そのため一番のおススメにはしませんが、今後もガッツリとソフト開発をされる方には良い選択肢だと思います。

:::note info
[GNUWin32](https://gnuwin32.sourceforge.net/packages/make.htm)によるインストールが紹介されることもありますがこちらは最終更新が2006年とずいぶん前なのでオススメできません
:::
PowerShell から PowerShell を新たに管理者権限で開く

---
**Shell オブジェクト バージョン**
```
$Exec = "PowerShell"
$Opti = "-NoExit -NoProfile -ExecutionPolicy Bypass -Command `$DIR = '${Env:__CD__}';" + @'
  Set-Location -Path $DIR
  Write-Host \"ここでは \"\" を \ でエスケ－プする\"
  ### Script Here ###


  ### Script :EOF ###
'@
$Dire = $Env:__APPDIR__

$Shell = New-Object -ComObject "Shell.Application"
$Shell::ShellExecute($Exec, $Opti, $Dire, "RunAs", 1)
```

`$Exec` に実行ファイルを代入
`$Opti` は引数を設定
* `-NoExit`
    * 自動終了させない
* `-NoProfile`
    * プロファイルを読み込まない
* `-ExecutionPolicy Bypass`
    * PS スクリプト実行ポリシーを無制限にする
* `-Command`
    * このオプション以降が文字列の場合、その後のすべての引数を実行するコマンドとして受け取る
    * ``` `$DIR = '${Env:__CD__}';```
        * 現在のディレクトリを変数 $DIR に代入
    * `Set-Location -Path $DIR`
        * カレントディレクトリを $DIR に変更
    * `Write-Host \"ここでは \"\" を \ でエスケ－プする\"`
        * リテラルの文字列に使う二重引用符をバックスラッシュでエスケープする
        * 二重引用符自体を文字列に使うには、エスケープされた二重引用符の二組をペアにして記述する（`"` ＝ `\"\"`、`" "` ＝ `\"\" \"\"`）
* `$Dire = $Env:__APPDIR__`
    * 現在実行している PowerShell の実行ファイルが存在するディレクトリを変数 $Dire に代入
* `New-Object -ComObject "Shell.Application"`
    * PowerShell で COM オブジェクトを使えるようにする
* `$Shell::ShellExecute($Exec, $Opti, $Dire, "RunAs", 1)`
    * 以下をそれぞれ設定する
    * 第一引数は実行ファイル
    * 第二引数は実行ファイルに渡す引数
    * 第三引数は実行ファイルの開始ディレクトリ
    * 第四引数は実行ファイルに対して行う操作の動詞文字列
    * 第五引数は実行ファイルがどのようなウィンドウで表示されるか
---
**Start-Process コマンドレット バージョン**
```
Start-Process PowerShell `
  -Verb RunAs `
  -WindowStyle Normal `
  -WorkingDirectory "${Env:__APPDIR__}" `
  -ArgumentList "-NoExit -NoProfile -ExecutionPolicy Bypass -Command", 
    'Write-Host \"ここでは \"\" を \ でエスケ－プする\";', 
    "`$DIR = '${Env:__CD__}';", 
    'Set-Location -Path $DIR;', 
    @'
### Script Here ###


### Script :EOF ###
'@
```
---
JavaScript難しくない…？

JavaScriptが今まで学んできた言語と一風変わった書き方で戸惑っています。
正直、挫折しそうですが…思い返せばPHP、Laravelを学び始めた時もこんな感じで挫折しそうだったので、書いていればなんとかなると思っています。
手を動かしていれば慣れるはず！

最近勉強を終えて帰る時間が遅くなっているため、Qiitaに書くブログが短くなっています。
そもそも何を書くかあまり思い浮かばないわけで…。
本当なら技術の話をアウトプットしたいのですが、それでも特に書くことがありません。
Node.jsやJavaScriptビルドツールのインポートパスの仕組み：index.tsxなどを使った簡略化

## アジェンダ
JavaScriptやTypeScriptを使ってプロジェクトを開発する際、`import { Test } from "../test";`のように相対パスでフォルダを指定すると、そのフォルダ直下にある`index.js`、`index.jsx`、`index.ts`、`index.tsx`が特別扱いされ、なぜファイル名を指定せずにインポートできるのか、その仕組みについて簡単にまとめます。

## デフォルトファイルの読み込み
Node.jsや多くのJavaScriptビルドツール（Webpack、Babelなど）では、フォルダを指定してインポートした場合、そのフォルダの直下にある`index`ファイルを自動的に探しに行くという規約があります。具体的には、`../test`と指定すると、自動的に`../test/index.js`、`../test/index.jsx`、`../test/index.ts`、`../test/index.tsx`などを探し、見つけた場合はそれをインポートします。

## モジュールのエクスポートとインポートの簡略化
`index.tsx`をフォルダのエントリーポイントとして利用することで、そのフォルダ内の他のファイルやコンポーネントを統合的に管理できます。これにより、インポート文が簡略化され、コードの可読性が向上します。

## 具体例

例えば、以下のようなディレクトリ構造があるとします：

```
project
├── test
│   ├── index.tsx
│   └── otherComponent.tsx
└── types
    └── index.ts
```

`index.tsx`ファイルの内容が以下のようになっているとします：

```tsx:index.tsx
import { FunctionComponent } from "react";
import { Type } from "../../types/index";

type TestProps = {
    value: Type;
}

export const Test: FunctionComponent<TestProps> = ({ value }: TestProps) => {
    return (
        <>
            <div className="test">
                {value}
            </div>
        </>
    );
}
```

この場合、`index.tsx`を`import { Test } from "../test";`でインポートできる理由は、`test`フォルダのエントリーポイントとして`index.tsx`が利用されるためです。この規約により、開発者はファイル名を指定せずに簡潔にインポートを記述できます。

## まとめ
import { Test } from "../test";のようにフォルダ名だけを指定することで、フォルダのエントリーポイントであるindex.tsxやindex.jsなどを自動的にインポートできるのは、Node.jsやJavaScriptのモジュールシステムにおける一般的な規約に基づく動作です。この仕組みを利用することで、コードの可読性とメンテナンス性が向上させることができます。
AWS CloudWatch: クラウドアプリケーションを監視について

この内容はあくまでも個人のメモ用に残している内容です。

クラウドアプリケーションを運用する上で、その状態を把握することは不可欠です。性能、可用性、セキュリティに関する情報は、迅速な問題解決、コスト最適化、そしてビジネスの成功に大きく貢献します。しかし、膨大なデータの中から必要な情報を抽出し、適切なアクションを迅速に取ることは容易ではありません。そこで登場するのが、Amazon CloudWatchです。

### CloudWatchとは？

AWS CloudWatchは、AWSリソースやアプリケーションのパフォーマンス、可用性、セキュリティに関する情報をリアルタイムで収集、分析、可視化するサービスです。まるでクラウドアプリケーションの運転席に座って、あらゆる状況を把握できるような、強力なダッシュボードを提供します。

### ビジネスへのメリット

CloudWatchは、単なる監視ツールではありません。ビジネス価値を最大限に引き出すための強力なツールです。

* **問題の早期発見と解決:** 異常な動作を自動的に検知し、アラートを発することで、問題を早期に発見し解決できます。ダウンタイムを最小限に抑え、ビジネスへの影響を軽減します。
* **コスト最適化:** リソース使用状況を詳細に分析することで、無駄なリソースの使用を減らし、コストを最適化できます。
* **パフォーマンスの向上:** パフォーマンス指標を分析し、アプリケーションのボトルネックを特定することで、パフォーマンスを向上させ、ユーザーエクスペリエンスを改善できます。
* **セキュリティ強化:** セキュリティイベントを監視することで、潜在的な脅威を早期に発見し、適切な対策を講じることができます。

### 技術的な説明

CloudWatchは、以下のような様々な機能を提供することで、クラウドアプリケーションの監視を強力に支援します。

* **メトリクス:** CPU使用率、メモリ使用量、ネットワーク帯域幅など、AWSリソースやアプリケーションのパフォーマンス指標を収集します。
* **ログ:** アプリケーションやシステムからのログ情報を収集し、分析します。
* **アラート:** 設定した条件に基づいて、アラートを自動的に生成します。
* **ダッシュボード:** メトリクス、ログ、アラートを可視化し、分析を容易にするダッシュボードを提供します。
* **インサイト:** AIを活用して、潜在的な問題を検出し、推奨事項を提供します。

### 実装ガイド

1. **アカウントの作成:** AWSアカウントを作成し、CloudWatchコンソールにアクセスします。
2. **リソースの監視設定:** 監視対象のAWSリソースを選択し、メトリクス、ログ、アラートを構成します。
3. **ダッシュボードの作成:** 必要に応じて、メトリクス、ログ、アラートを可視化するダッシュボードを作成します。
4. **アラートの構成:** 特定の条件に基づいて、アラートを生成するルールを定義します。
5. **インサイトの有効化:** AIを活用して、潜在的な問題を検出し、推奨事項を得るために、インサイト機能を有効化します。

### ユースケースとケーススタディ

* **ウェブサイトのパフォーマンス監視:** ウェブサイトの応答時間、ページロード時間などのメトリクスを監視することで、ユーザーエクスペリエンスを改善できます。
* **サーバーレスアプリケーションの監視:** Lambda関数のパフォーマンスやエラー率を監視することで、アプリケーションの安定性を確保できます。
* **データベースのパフォーマンス最適化:** データベースのCPU使用率、メモリ使用量などを監視することで、パフォーマンスを最適化し、コストを削減できます。
* **セキュリティイベントの検知:** ログ分析により、不正アクセスやセキュリティ侵害などのイベントを検知することができます。

### ベストプラクティスと注意点

* **監視対象の選択:** 重要なリソースやアプリケーションを優先的に監視しましょう。
* **アラートの構成:** 適切な条件でアラートを構成することで、誤検知を減らし、必要なアラートのみを確実に受信できます。
* **データの保存:** メトリクスやログデータの保存期間を適切に設定しましょう。
* **コスト管理:** 監視対象のリソースやデータ量を適切に管理することで、コストを抑制できます。

### 他のAWSサービスとの統合

CloudWatchは、Lambda、S3、ECS、DynamoDBなど、多くのAWSサービスと統合されています。例えば、Lambda関数からのログデータをCloudWatch Logsに保存したり、S3バケットの容量使用状況を監視したりすることができます。

### 結論

CloudWatchは、AWSリソースやアプリケーションの監視、分析、そして最適化を強力に支援するサービスです。このブログ記事では、CloudWatchの概要、ビジネスへのメリット、技術的な説明、実装ガイド、ユースケース、ベストプラクティスを紹介しました。
【初学者 - 備忘録】Next.jsにおけるレンダリングの種類

Next.jsでは、以下の3つのレンダリングを使用する
- CSR（クライアントサイドレンダリング）
- SSR（サーバーサイドレンダリング）
- SG（静的サイト生成）

# CSR - クライアントサイドレンダリング
Client Side Renderingの略。

データフェッチやルーティングのすべてがクライアント上で行われる。
サーバーではなく、クライアント側にコードが全て配信されてからブラウザでコードが実行されて画面が生成される。

※Next.jsの開発ではクライアント側でのみ行いたい処理はuseEffectで囲む。

### 仕組みの流れ
①クライアントからHTTPリクエストがサーバーに飛ぶ
②リクエストの応じてレンダリング前のTHMLをクライアントに返却
③返ってきたHTMLとjavascriptのコードをもとに画面を構築
④画面構築中に追加の情報が必要であれば、クライアントからAPIサーバーにデータをリクエストを飛ばす
⑤戻り値としてJSONデータが返ってくる
⑥受け取ったデータから画面を構築
![FY24_神田のmiro - CSR.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890419/b4a1d19e-959b-127c-2b24-dba128d9fbbc.jpeg)


## メリット
- 静的なファイルの配置の身で動く
- サーバー側の負荷が軽い
## デメリット
- 初期描画に時間がかかる（ブラウザ側ですべてのコードから画面を構築するため）
- クローラーによってはSEO的な問題あり

<details><summary>クローラーについて</summary>

クローラーは、タイトルやメタタグからそのサイトの説明文を作ったりするもの。
検索結果の説明とかに載せるやつを勝手に作ってくれるやつのこと。

Googleは問題ないが、SNS系のクローラーはjavascriptの実行ができないものがあり、うまくタイトルなどを読み込んでくれない場合がある
</details>

# SSR - サーバーサイドレンダリング
Sever Side Renderingの略。

サーバーにリクエストが着たタイミングで動的にHTMLを生成。
外部APIへのデータの取得やコンポーネントのpropsの値を決定する処理を行い、HTMLを作成してクライアント側に返却する。

### 仕組みの流れ
①クライアントからHTTPリクエストをサーバーに飛ばす
②サーバーからAPIサーバーにデータを問い合わせ
③必要なデータがJSONファイルなどでサーバー側に返却される
④サーバー側でHTMLを生成
⑤生成されたHTMLがクライアントに返却
![FY24_神田のmiro - SSR.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890419/9a4fe561-078f-d90a-c808-6097cf107c40.jpeg)


## メリット
- 生成済みのHTMLを取得するのでSEOに強い

## デメリット
- 生成処理をすべてサーバー側でするので負担が大きい
- HTMLをクライアントに渡すまで時間がかかる

# SG - 静的サイト生成
Static Generationの略。

ビルド時にデータフェッチやpropsの値の決定を行い、HTMLを構築する。
クライアントからリクエストされたら、サーバー側で構築することなく、生成済みHTMLを渡す。

## 仕組みの流れ
①ビルド時にビルド用のコマンドをたたいてHTMLを生成
②生成時にデータが必要な場合はAPIサーバーにリクエストを送信
③返ってきた情報をもとにHTMLを生成
④出来上がったHTMLをサーバーに配置
⑤クライアントからリクエストされたパスに応じて生成済みHTMLを返す
![FY24_神田のmiro - SG.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890419/8643df29-0678-430e-0d5c-0d819c614210.jpeg)

# メリット
- 構築済みのため表示速度が高い
- SEO問題なし

# デメリット
- 更新頻度が高い動的な処理には向かない

# 基本構成
基本的にはSG。
動的に作成する必要があるページはSSR。
近年ではSSRを使うことが多い。キャッシュをうまく使えば効率よくできるから。
テーブル名に括弧を使うとQueryBuilderで詰む

# いいたいことはこれだけ
* DBやテーブル名に「_」以外の半角記号は入れないようにしよう
* QueryBuilderを用いる時に「()」とか入ってるカラムが入ってると詰むよ
* 削除が無理だったら大人しく生のSQLを書こう

# いきさつという名の自語り
C#で機能を移行するプロジェクトにて、SqlKataを用いていた
とあるテーブルに括弧が使われていたのだが、Where区を書いたところ失敗した。なんならSelectでも失敗していた（ただし「```SelectRaw("`name(myoji)` as firstName")```」のような書き方であれば成功した）
SqlKataの書き方に問題があるかもと、類似したSQLを作成してみたが、それは成功した
どういうこっちゃとリーダーに相談し、()は付けちゃいけないという結論になり、括弧に該当する箇所を「_」に変更してもらった
【割り勘アプリ】QuickSplit - メモ帳よさようなら、みんなでワイワイ割り勘管理！[個人開発]

## 初めに
こんにちは！24卒で某大手ECサイトの保守・運用会社に入社した新米エンジニアです。最近はbrSEとして中規模ECサイトの案件を中国側とやり取りする業務をしています。
そんな空いた時間や帰宅後の時間を使って、ちょっとしたサービスを作ってみました。その名も「QuickSplit」！
## QuickSplitって何よ？
「QuickSplit」は、グループでの割り勘を簡単に管理できるWebアプリです。
URL: https://quickaplit.web.app/
友達との旅行や飲み会で、「あれ？誰が何を払ったっけ？」「いくら返せばいいの？」なんて悩んだことありませんか？私はよくあります（笑）
そんな時、メモ帳でガリガリ計算して、LINEで「おい、1500円な」なんて送るのも面倒くさい...。そこでQuickSplitの出番です！
![](https://storage.googleapis.com/zenn-user-upload/836fb146f38a-20240808.png)

## なぜ作ったの？
正直、メモ帳で割り勘管理して友達に連絡するのが面倒くさかったんです（笑）。「いっそのこと、みんなで見られるようにしちゃえば良いんじゃね？」というノリで始めました。

## 技術スタック

フロントエンド: React
バックエンド: Firebase (Authentication, Firestore, Hosting)
UI: Material-UI
状態管理: React Hooks
その他: QRコード生成 
(qrcode.react)--
![](https://storage.googleapis.com/zenn-user-upload/8ac444d0afad-20240809.png)
＊モザイクの入れ方がわかりませんでしたTT

## QR招待
生成されたQRにURLを埋め込むことで実現できました
```
<Dialog open={qrDialogOpen} onClose={() => setQrDialogOpen(false)}>
  <DialogTitle>グループ招待QRコード</DialogTitle>
  <DialogContent>
    <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      <QRCode value={`https://quickaplit.web.app/join/${groupId}`} size={256} />
      <Typography variant="body2" sx={{ mt: 2 }}>
        このQRコードをスキャンしてグループに参加できます。
      </Typography>
    </Box>
  </DialogContent>
</Dialog>

```
## データフロー

ユーザーがグループを作成 → Firestoreに保存
グループメンバーを招待 → Firestoreに招待情報保存
支出を入力 → Firestoreに支出情報保存
リアルタイムリスナーで支出情報を取得 → 画面に表示
割り勘計算 → クライアント側で計算し、結果を表示

Firestoreのリアルタイムリスナーを使用しているので、誰かが支出を入力したら、他のメンバーの画面にもリアルタイムで反映されます。まるで魔法のように！（実際はただのWebSocket通信ですが...）
## これから直したいところ
正直、まだまだ改善の余地がたくさんあります。例えば：

一部動作していない機能の修正（すみません、見つけたらこっそり教えてください...）
UIの改善（もっとオシャレに！）
精算機能の追加（◯◯さんは△△さんに□□円払ってね、みたいな）
プッシュ通知機能（「おい、まだ払ってねーぞ」機能）

## 最後に
QuickSplitを使えば、もう二度と「割り勘の計算ミスで友情が壊れる」なんてことはありません！（たぶん）
ぜひ使ってみてください。そして、「ここ改善した方がいいよ」とか「こんな機能欲しい！」というアイデアがあれば、ぜひコメントで教えてください。
みなさんの「割り勘ストレス」が少しでも減りますように
データ型にエイリアスを付ける（C#12）

## 参考
この記事は、以下の動画を参考にしています。
詳しくは、動画をご覧ください。

https://youtu.be/GiVZzrL2EIM?si=bFoIUI6Sxmlgp452

以下の記事も、参考にしてください。

https://ufcpp.net/study/csharp/sp_namespace.html#using

## using alias
C#11以前でも、データ型にエイリアス（別名）を付けることはできました。

```C#
using IntList = System.Collections.Generic.List<int>;
```

C#12からは、以下のものに対しても、エイリアスを付けることができます。
- C#のキーワードとして用意されているデータ型
  ```C#
  using Integer = int;
  ```
- 配列
  ```C#
  using IntegerArray = int[];
  ```
- Null許容型
  ```C#
  using NullableInteger = int?;
  ```
- タプル
  ```C#
  using Person = (string firstName, string lastName);
  ```
Next.jsの_app.tsxでdefault exportを使用しなくてはいけない理由

## アジェンダ
Next.jsでは、`_app.tsx`ファイルが全てのページのエントリーポイントとして機能します。
このファイルでdefault exportを使用しなければならない理由を簡単にまとめます。

## `_app.tsx`の役割
`_app.tsx`は、アプリ全体に共通するレイアウトや状態管理、CSSスタイルを設定するために使用されます。すべてのページコンポーネントは、このファイルを経由してレンダリングされます。

```tsx
import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;
```

## default exportが必要な理由
必要な理由は、一つだけなのですが、Next.jsは、`_app.tsx`からdefault exportされたコンポーネントを探し、エントリーポイントとして使用します。default exportがないと、Next.jsは正しく動作しません。
named exportだと以下のエラーを吐きます。

```sh
Error: The default export is not a React Component in page: "/_app"
```

必要な理由はこれだけになります。
Next.js Reactプロジェクトにおける型定義の管理方法

## アジェンダ

TypeScriptを使用したNext.js、Reactプロジェクトにおいて、型定義を適切に管理することで、コードの可読性と保守性を向上させることができます。
ここでは、型定義の管理方法とその活用法について、自分なりにベストプラクティスを模索したものをまとめます。


:::note info 
重要なポイント
1. **`.d.ts` ファイルでの型定義**: 型定義を `.d.ts` ファイルに分離するのではなく、通常の TypeScript ファイル (`.ts` や `.tsx`) 内に型定義を含める方が、開発プロセスをシンプルにするために推奨されます。

2. **型定義のコロケーション**: 型定義とそれに関連するコンポーネントを同じ場所に配置する「コロケーション」の実践は、特に大規模なプロジェクトにおいて、コードの管理を容易にし、プロジェクトの拡張性を高める方法として推奨されています。
:::

## 型定義の管理方法

従来、型定義を管理するために型専用のフォルダを設けることが一般的でしたが、大規模なプロジェクトでは管理が煩雑になることが指摘されています。特に、型定義ファイル（`.d.ts`）を分離することは、コンポーネントの増加に伴い、保守性を低下させる可能性があります。

※詳しくは以下参照。

https://zenn.dev/qnighy/articles/9a6a0041f2a1aa

## 型定義のコロケーション

「コロケーション」という考え方に基づき、互いに密接に関わる型定義とコンポーネントは、同じファイルまたはディレクトリに配置することが推奨されます。これにより、コンポーネントが増えたとしても管理が容易になります。

### コンポーネントと型定義の同居

具体的な例として、コンポーネントとそのProps型定義を同じファイルに置く方法を紹介します。これにより、コードの可読性とメンテナンス性が向上します。

```tsx:components/Button.tsx
import { FunctionComponent, ComponentPropsWithoutRef } from "react";

// Props型をコンポーネント内で定義
type ButtonProps = ComponentPropsWithoutRef<"button">;

export const Button: FunctionComponent<ButtonProps> = ({ onClick, className }) => {
  return <button onClick={onClick} className={className} />;
};
```

### 型の再利用方法

他の場所で同じProps型を再利用したい場合、`ComponentPropsWithoutRef`を使用して型を抽出する方法が便利です。

```typescript:型の抽出例
import { ComponentPropsWithoutRef } from "react";
import Button from "./Button";

type ButtonProps = ComponentPropsWithoutRef<typeof Button>;
```

※詳しくは以下参照。

https://qiita.com/honey32/items/dbf3c5a5a71636374567

## まとめ

型定義を専用フォルダに分離するのではなく、コンポーネントと同じ場所に配置することで、コードのスケーラビリティとメンテナンス性が大幅に向上します。
また、型定義ファイル（`.d.ts`）の使用には注意が必要であり、通常は標準のTypeScriptファイル内で型定義を行うことが推奨されます。

## 参考
- [`*.d.ts` ファイルをコミットする前に知ってほしい4つのこと](https://zenn.dev/qnighy/articles/9a6a0041f2a1aa)
- [そのファイル、本当に hooks/・utils/ に入れるんですか？ ―― React プロジェクトを蝕む「見かけ駆動パッケージング」 #設計 - Qiita](https://qiita.com/honey32/items/dbf3c5a5a71636374567)
CLFクラウドのコンセプトについて（その1）AWSクラウドの利点を定義する

# はじめに
AWS認定であるクラウドプラクティショナー(CLF)の出題範囲である、
クラウドのコンセプトについて学ぶ。

## クラウドの分野について
* ①AWS クラウドの利点を定義する。
* ②AWS クラウドの設計原則を特定する。
* ③AWS クラウドへの移行の利点と戦略を理解する。
* ④クラウドエコノミクスのコンセプトを理解する。

以上4項目がAWSの提示しているクラウドのコンセプトです。
今回はこの中から**①AWSクラウドの利点を定義する**を解説します。

## ①クラウドの利点を定義する
こちらの項目では
**AWSクラウドの価値提案**が対象知識となっています。
対象となるスキルは以下の3つです

* ①規模の経済についての理解(コスト削減など) 
* ②グローバルインフラストラクチャの利点の理解(デプロイのスピード、グローバルリーチなど)
* ③高可用性、伸縮性、俊敏性の利点の理解

## ①規模の経済についての理解(コスト削減など)
規模の経済とは、AWSがサービス提供規模を拡大することにより、
増えた顧客への値下げ等の還元をする仕組みのこと。

## ②グローバルインフラストラクチャの利点の理解<br>　(デプロイのスピード、グローバルリーチなど)
この項目で大切なポイントは主に2つあります。

* ①冗長性とデータ保護
* ②高速で安全なコンテンツ配信
<br></br>
* **①冗長性とデータ保護**
 AWSのインフラは複数のリージョンに分散し、障害を見越した設計をすることで
 運用上のリスクを減らす、高可用性を実現しています。
 <br></br>
* **②高速で安全なコンテンツ配信**
 グローバルエッジネットワークを構築されていて、
 世界各地にあるPoint of Presence(POP)を通じて
 高速で安全なコンテンツ配信をすることができる。

## ③高可用性、伸縮性、俊敏性の利点の理解
この項目で大切なポイントは、主に3つあります。

* ①高可用性
* ②伸縮性
* ③俊敏性
<br></br>
* **①高可用性**
 EC2インスタンスが唐突に落ちたり、アベイラビリティゾーンが
 消滅したりしてもシステムが稼働し続けられる、
 何か障害があっても、システムの停止時間をなるべく少なくすることを指します。
 **Design for Failure**と一緒に使うことが多い。
 <br></br>
* **②伸縮性**
 リソースの性能を柔軟にスケールアウトしたり、スケールインすること。
 AWSの**Elastic**は伸縮性が高く、弾力性があるという意味。
<br></br>
* **③俊敏性**
 変化に迅速に対応できる能力（リソースの調達）、コンピューティングリソースを
 すぐに起動できること。
 
### おわりに
以上が「AWSクラウドの利点を定義する」についてでした。
今回解説したポイント以外にも、出題はあるかと思いますが、
基礎的な知識として大切なポイントです。

### 参考文献
・https://d1.awsstatic.com/ja_JP/training-and-certification/docs-cloud-practitioner/AWS-Certified-Cloud-Practitioner_Exam-Guide_C02.pdf
・https://www.youtube.com/watch?v=2a9w43E8irg
・https://workjam.co.jp/aws-global-infrastructure/
・https://qiita.com/taktak813tec/items/e9780170746ab4c3b085
・https://aws.amazon.com/jp/about-aws/global-infrastructure/
【Revit】AdWindows.dllとは何か

# 概要
Revitのアドイン開発に関連するAPIのひとつに、「AdWindows.dll」というdllがありました。
このdllについて、少しまとめました。

# Revitの公式にはサポートされていないdllだった
Revit APIの公式ドキュメントにはAdWindows.dllの記載がありませんでした。
また、Revitにおいては公式にサポートがされていないdllでした。

https://forums.autodesk.com/t5/revit-api-forum/adwindows-dll-api-documentation/td-p/9738511

# どうやらAutoCAD.NETのAPIらしい
AdWindows.dllはRevitのAPIではなく、AutoCAD.NET APIのひとつらしいです。なので、特定のケースではRevitの環境でも利用できる可能性はありますが、上記に記載したようにAutodeskからの公式サポートやドキュメントがないため、自己責任で利用する必要があります。

# このAPIで何ができるの？
自分がRevitでこのAPIを利用した場面は、下記の2つでした。

① コードから特定のRevitのタブをアクティブにする
```C#  
/// <summary>
/// 特定のリボンタブをアクティブにする
/// </summary>
/// <param name="tabName">アクティブにするリボンタブの名前</param>
public void ActivateRibbonTabByName(string tabName)
{
    if (tabName == null) return;

    // AdWindows.dllを使用して、特定のリボンタブを見つける
    var ribbon = Autodesk.Windows.ComponentManager.Ribbon;
    var tab = ribbon.FindTab(tabName);
    if (tab == null) return;

    // 見つかったリボンタブをアクティブにする
    ribbon.ActiveTab = tab;
}
```
② ユーザーが特定のリボンタブを押下したときにイベント処理を走らせる
```C#  
/// <summary>
/// イベントを購読する
/// </summary>
private void SubscribeEvent()
{
    // AdWindows.dllを使用して、特定のリボンタブを見つけてイベントを接続する
    // ※①のFindTab()とは異なる見つけ方。Tabsでリボンタブの一覧を取得できる
    foreach (var Tab in Autodesk.Windows.ComponentManager.Ribbon.Tabs)
    {
        if (Tab.Name == "サンプル")
        {
            // イベント接続
            Tab.Activated += new EventHandler(TabActivated_SampleTab);
            break;
        }
    }
}

/// <summary>
/// 「サンプル」タブが選択状態になった際のイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TabActivated_SampleTab(object sender, EventArgs e)
{
    // 何かしらの処理
}
```
:::note Info
② についてはTab.Deactivatedというものもあり、こちらは特定のタブが選択状態から未選択状態になったときに走る。
:::

上記のように、Revitのタブに関して特定の操作を行いたいときには使用する (使用したい) 場面がありそうです。

## AdWindows.dllに関するリンク集
- [Automation, Ribbon Panel, ItemExecuted and Vacation](https://thebuildingcoder.typepad.com/blog/2015/02/automation-ribbon-panel-itemexecuted-and-vacation.html
)
- [AutoCAD .NET API：リボンタブの表示制御](https://www.autodesk.co.jp/support/technical/article/caas/tsarticles/ts/7DuScEejGXHJbQvt2VLkcz.html)
Azure Files (Azure ファイル共有) のスループット

こんにちは、アーキテクトのやまぱんです。

今回は Azure Files のスループットについてです。
なお、今回は 主にStandard ファイル共有を取り上げて検証しています。
（Azure Files 高 SKU の Premium ファイル共有もあります）


補足コメントや質問、<font color="red">**いいね、拡散**</font>、是非お願いします🥺！
間違ってたら<font color="red">**優しく**</font>教えてください！

# Azure Files のスループット


## 大きなファイル共有となったことで変わるスループット(Azure Files 共有 単位のスループット)
+ 大きなファイル共有の規定の有効化
現在 Azure Files はLRS冗長でも規定で ”大きなファイル共有” オプションが有効になっている。
そのため、スループットも以前に比べて格段に良くなっている。
Azure Portal から以下の画面でも確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/883e5549-2d9f-e56c-73b6-6667fb9632d9.png)

MS Learn としてはこちらが参考になります。（執筆辞典では GRS/Geo冗長 前提の記載となっていますが、LRSでも同様です)
* geo 冗長共有の新しい制限
https://learn.microsoft.com/ja-jp/azure/storage/files/geo-redundant-storage-for-large-file-shares#new-limits-for-geo-redundant-shares
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/88dbc2fa-2c29-8a34-372b-b4a2221af6a9.png)


さらにリンク先をたどると以下です。
* ストレージ アカウントのスケール ターゲット
https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-scale-targets#storage-account-scale-targets
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/50a10e5a-103e-0960-0550-35611b1d3eb1.png)

:::note info
つまり、東日本リージョンなど対応しているリージョンの場合現在の Azure Files(standard)  の Azure Files 共有単位のスループットは以下
* イングレス: 7,152 MiB/秒
* エグレス: 14,305 MiB/秒
:::

## ファイル単位のスループット
一方、Azure Files のスループットにはAzure Files 共有単位のとは別にファイル単位のスループットがあります。

+ ファイルのスケール ターゲット
https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-scale-targets#file-scale-targets
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/c4cdceca-5af9-1444-403d-66a8337f0c00.png)


:::note info
つまり Azure Files (standard) のファイル単位のスループットは以下
* イングレス: 60 MiB/秒
* エグレス: 60 MiB/秒
:::


## 次回
次回は実際にスループットを測定してみたいと思います。
バイトダンス、OpenAIのSora対抗AIビデオアプリをリリース

本記事では[reuters](https://www.reuters.com/)より翻訳します。

北京、8月6日（ロイター） - バイトダンスは、テキストプロンプトに基づいてビデオを生成できるソフトウェアの提供を拡大し、ChatGPTの開発者OpenAIがターゲットにしている新興市場に参入する多くの中国の技術企業に加わりました。

Microsoftが支援するOpenAIが2月にテキストからビデオへのモデルSoraを発表して以来、中国の企業は迅速に同様のツールを開発し、いくつかのモデルをユーザーが利用できるようにしました。

バイトダンス傘下のFaceu Technologyが開発したJimeng AIは、7月31日にAndroidでリリースされた後、現在Apple App Storeで中国のユーザーが利用できるようになっています。

短編動画アプリTikTokの親会社がテキストからビデオへのモデルを発表するのは、中国での最近の一連の類似モデルリリースに続くものです。

中国最大のビデオアプリの一つであるKuaishouは、先月末にKling AIテキストからビデオへのモデルをグローバルオーディエンスに公開しました。そのベータ版は全世界でアクセス可能で、登録にはメールアドレスのみが必要です。

中国のAIスタートアップであるZhipu AIも先月、ビデオ生成モデルYingを発表し、その数日後には別のスタートアップであるShengshuが正式にViduアプリをリリースしました。

Faceu TechnologyはバイトダンスのJianying事業の一部で、これはビデオ編集アプリCapCutでよく知られています。

Jimeng AIは月額69元（9.65ドル）、単月79元、年額659元のサブスクリプションを提供しています。各プランでは、月に約2,050枚の画像または168本のAIビデオを作成できます。

AIを活かして、動画を生成や強化するソフトを続々登場しています。ここでは、動画に興味があるなら[UniFab](https://ja.unifab.ai/)がおすすめです。 UniFab は、強力な[AIで高画質化](https://ja.unifab.ai/video-upscaler-ai.htm)が簡単に実現できます。直感的なインターフェイスと豊富な機能により、ビデオ制作が簡単かつ効率的になります。あなたの創造力をさらに高めるUniFabをぜひ体験してください!
[paiza] 「mod7占い」にC#で挑戦しました（paizaランク S相当）

[paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう！」](https://qiita.com/official-events/9ab96aa95d62fe3cbdd7)の参加記事になります。

[mod7占い](https://paiza.jp/works/mondai/s_rank_skillcheck_sample/mod7)に挑戦してみました。

## 経緯
最近他人のコードレビューやフロントエンドのVM処理ばかり書いていて、ロジック的なコードを全く書いてないな～と思っていた矢先にイベントを目撃したので参加した次第。
たまには頭の運動をしとこうというアレです。
とりあえず、使い慣れているC#で突撃。

## 答案

```cs
using System;

namespace ModSevenFortune
{
    public class Program
    {
        static void Main()
        {
            var n = uint.Parse(ReadLineAndTrim());
            long[] numbers = new long[n];

            for (int i = 0; i < n; i++)
            {
                numbers[i] = long.Parse(ReadLineAndTrim());
            }

            var count = CountLuckyCombinations(numbers);
            Console.WriteLine(count);
        }

        private static string ReadLineAndTrim() => Console.ReadLine().Trim();

        private static int CountLuckyCombinations(long[] numbers)
        {
            var count = 0;

            if (numbers.Length < 3) return count;

            for (var i = 0; i < numbers.Length - 2; i++)
            {
                for (var j = i + 1; j < numbers.Length - 1; j++)
                {
                    for (var k = j + 1; k < numbers.Length; k++)
                    {
                        if ((numbers[i] + numbers[j] + numbers[k]) % 7 == 0)
                        {
                            count++;
                        }
                    }
                }
            }

            return count;
        }
    }
}
```

## 反省
イキってLINQで書こうとして、タイムアウトで一敗。
入力として与えられる数字の範囲が`0 <= V < 2^32`と言われてるのに`int`で手を付け始めてしまい、ランタイムエラーやオーバーフローで二敗。
その後`uint`でやり直すも、和でオーバーフローし三敗。

`uint`では捌けない箇所を`long`に直した上記のコードで正答となりました。

ロジックとかより「メモリと型」という超初歩的なところでコケまくってしまい、自分恥ずかしいッス。

## 感想
完走した感想ですが、たまにはこういう頭の運動をしておくと楽しくていいですね。
この手のコーディングはゲーム感覚で取り組めるのでおもろいです。

ロジックについては、もっとスマートなやり方はきっとあるんでしょうが、無理せず愚直にやっておくが吉（経験則）。
最初は再帰とかも活用してオシャレに捌いてやろうかと思いましたが、そんなのは自己満ですからに（そしてタイムアウトで落ちる）。
そもそも、パフォーマンスを意識する必要がある文脈では、できるだけ原始的な方法であるべきですしね。可読性が求められている文脈でもないですし。