OmniAICreator/Qiita-1.07M huggingface dataset:
SourceTree（ソースツリー）| fetch（フェッチ）| リモートリポジトリの内容を取得

##  fetch（フェッチ）とは
Git：リモートリポジトリの内容をローカルリポジトリに取得する機能
英語：取ってくる、呼んでくる、連れてくる
## SourceTree のやり方
SourceTree は自動で fetch をしてくれるが、反映されない場合があるため強制的に行うこともできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492954/0571a92e-99a3-88a1-d9e0-aac98a826039.png)
左上のボタンをクリック
## プル = フェッチ + マージ
フェッチ：リモートリポジトリの内容をローカルリポジトリに取得
マージ：取得した内容を反映
フェッチはプルの機能の一部で、マージする前に変更を確認することができる。確認後に反映させたい場合はプルを行う
### 参考
- https://yttm-work.jp/git/git_0008.html
-
【React】あるHTML要素が画面内に表示されている時だけtrueを返すようなhooksを作る

# はじめに
Webアプリケーションを開発する中であるHTMLの要素が画面内にあるかどうか知りたいことはよくあります。例えば無限にデータを読み込む必要がある時はスクロールが一番下のコンテンツまで到達したという情報、つまり一番下のコンテンツが画面内にあるかどうかが必要となります。他にも、対象のコンテンツがユーザーに表示された数を計測したい時にも使えます。
この記事ではある要素が画面内に現れた時に`true`、存在しない時に`false`を返すようなCustom Hooksを作成します。

# 実装
今回作成するコードの全景はこのようになっています。
```ts
import { RefObject, useEffect, useState } from 'react';

export const useInView = (ref: RefObject<HTMLElement>) => {
  const [inView, setInView] = useState(false);

  useEffect(() => {
    if (!ref.current) {
      return;
    }

    const observer = new IntersectionObserver(([entry]) =>
      setInView(entry.isIntersecting),
    );
    observer.observe(ref.current);

    return () => {
      observer.disconnect();
    };
  }, [ref, setInView]);

  return inView;
};

```
引数には監視対象の要素を参照するような`ref`を渡します。
そして、`useState`を用いて監視対象の要素が画面内に現れたら`true`を返すような状態を作成します。ここで作成した`inView`はこのhooksの返り値となります。

残りの部分は監視を行うように設定をする`useEffect`です。
```ts
useEffect(() => {
  if (!ref.current) {
    return;
  }

  const observer = new IntersectionObserver(([entry]) =>
    setInView(entry.isIntersecting),
  );
  observer.observe(ref.current);

  return () => {
    observer.disconnect();
  };
}, [ref, setInView]);
```
まずは、余計なことを考えないように`ref.current`がFalsyな値(このケースではnull)の時は監視対象の要素が`ref`で参照されていないと判断して早期returnします。
そして、`ref`が監視対象の要素を参照するようになったら、[交差オブザーバーAPI](https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API)を用いて画面内に`ref.current`で参照している要素が表示されているときは`inView`を`true`、表示されていないときは`false`に設定させます。
この設定は異なるライフサイクル間で引き継ぐとバグの原因になるので、アンマウント時に解除されるようにクリーンアップ関数も書きます。

# デモ
このhooksを利用方法の一例として以下のようなデモを作成しました。

https://codesandbox.io/embed/silly-swartz-n2q7i5?fontsize=14&hidenavigation=1&theme=dark

refが画面内に現れている時だけ表示するメッセージが変わるようなコンポーネントになっています。

# さいごに
ライブラリなどを利用せずに、ReactとブラウザAPIだけで簡単に作成することができるのでこれに近しいことがしたい場合はぜひご活用ください。
boto3.Sessionを利用した場合のGSIに対するクエリの書き方

DynamoDBのGSIに対してクエリをかける方法を調べたのでまとめます。


## 結論
```python
dynamodb = boto3.Session(profile_name=profile_name).client("dynamodb")
response = dynamodb.query(
            TableName="TABLE_NAME",
            IndexName="INDEX_NAME",
            KeyConditionExpression="index_key = :index_key",
            ExpressionAttributeValues={":index_key": {"S": "00000000"}},
        )
```

レスポンスはItemsをキーとしたオブジェクトが返ってきます。
```json
{'Items':[{"index_key":{"S":"00000000"}, "primary_key":{"S":"pk1"},"sort_key":{"S":"sk1"}}],}
}

```

リクエストでもレスポンスでも型を（文字列型ならば"S"のように）指定をしなければいいけないというところで躓きました。

## 参考文献
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/getting-started-step-7.html
discord.pyのインタラクションを遅らせる方法

#discord.pyのインタラクションを遅らせる方法

[discord公式](https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction)の以下の文

> Interaction tokens are valid for 15 minutes and can be used to send followup messages but you must send an initial response within 3 seconds of receiving the event. If the 3 second deadline is exceeded, the token will be invalidated.

インタラクションを発生させてから3秒以内に返信しろって

結構自由度奪ってると思うんですけど

それが嫌なら`followup`を使えということらしい

## 制限回避の送信コード

例として、以下のコードはスラッシュコマンドで打たれたテキストをグーグルで調べて結果を返すという処理を書いています
```python
@tree.command(name="google")
async def google_command(interaction: discord.Interaction,text:str):
    ##
    ##
    # ここで送信されたテキストをもとにgoogleで検索し結果を受け取る処理を書く
    ##
    ##
    result = #結果のテキスト
    await interaction.response.send_message(result)
```
このままだと検索をしている間に3秒かかってしまうこともあるので
以下のようなエラーを返すことがあります。
```
NotFound: 404 Not Found (error code: 10062): Unknown interaction
```

そこで回避するのが`followup`です。

```python
@tree.command(name="google")
async def google_command(interaction: discord.Interaction,text:str):
    await interaction.response.defer()
    ##
    ##
    # ここで送信されたテキストをもとにgoogleで検索し結果を受け取る処理を書く
    ##
    ##
    result = #結果のテキスト
    await interaction.followup.send(result)
```
`defer()`で返答を遅延させて、`followup`で送信する方法です。
ただしこの`followup`はwebhookになるので注意。

## 制限回避の編集コード
個人的にはこっちをよく使います。
それこそ今流行りのchatGPTを使って会話とかはこっちのほうが相性いいんじゃないかな。

```python
@tree.command(name="reply")
async def reply_command(interaction: discord.Interaction,text:str):
    message.id = #もとからあるメッセージ
    await interaction.response.defer()
    ##
    ##
    # chatGPTで返答を受信
    ##
    ##
    result = #結果のテキスト
    await interaction.followup.edit_message(message_id,content=result)
```
[JavaScript] 数字入りの文字列を「いい感じに」並べ替えるオプション


## 普通にソートすると

以下のような配列をソートすることを考える。

```ts
['1日', '2日', '11日', '21日']
```


JavaScript組み込みの`sort`関数を使うと、

```ts
console.log(['1日', '21日', '2日', '11日'].sort());
// => Array ["11日", "1日", "21日", "2日"]
```

このように辞書順で並び替えられるため、直観的でない順序になってしまう。

## sort関数にオプションを渡すと

sort関数にオプションを渡すことで、数値順を考慮した並べ替えを行うことができる。

```ts
console.log(['1日', '21日', '2日', '11日'].sort(new Intl.Collator("ja", { numeric: true }).compare));
// => Array  ["1日", "2日", "11日", "21日"]
```

`{ numeric: true }`のところが重要で、このオプションを渡すと「数値が入った文字列」をいい感じに並べ替えてくれるようだ。

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

## まとめ

- JavaScriptの配列のsort関数をそのまま使うと、辞書順で並べ替えられるため直観的でない順序になることがある。
- `Intl.Collator`を使いsort関数にオプションを渡すと、いい感じに並べ替えられる。

`Intl.Collator`には他にも便利なオプションが多数あるようですので、活用していきたい。
discord.pyでスラッシュコマンドをサーバー限定にする

# discord.pyでスラッシュコマンドをサーバー限定にする

意外と躓いたのでメモ
2.0以降discordモジュールはいろんなのでてるけど
今年更新決定したRapptz/discord.pyを引き続き使っていくことにします。

## 実際のコード
```python
import discord
from discord import app_commands,ui

client = discord.Client(intents=discord.Intents.all())
tree = app_commands.CommandTree(client)

@client.event
async def on_ready():
    #syncはあんまりon_ready()よくないらしいけどとりあえず。
    await tree.sync(guild=discord.Object(id={サーバーID}))

@tree.command(name="test",description="テストです")
@discord.app_commands.guilds({サーバーID})
async def test_command(interaction: discord.Interaction):
    #なんか処理

client.run({discord トークン})
```


最初以下の2つをどちらかしか入れていなくてうまく機能しなかった。。。
```python
await tree.sync(guild=discord.Object(id={サーバーID}))
```

```python
@discord.app_commands.guilds({サーバーID})
```

当然ギルドコマンドになるためDMとかでは表示もされないけど
DMを使えなくするには以下の方法もあるらしい
```python
@discord.app_commands.guild_only()
```
mathライブラリ(Python3)

Python3でmathライブラリを使う方法です。

```python3
# mathライブラリ
# 新規作成 2023/3/13

# mathライブラリを読み込む
import math
# √2
print(math.sqrt(2))
# 3.5より大きい最小の整数
print(math.ceil(3.5))
# 3.5より小さい最大の整数
print(math.floor(3.5))
# 12,20,8の最大公約数
print(math.gcd(12,20,8))

# 銀行まるめ
print(round(3.5))
print(round(2.5))

# 掛け算の結果の論理評価
print(0.1 * 3 == 0.3)
print(math.isclose(0.1 * 3,0.3))
```
object detection 確認記事集

## 記事の目的
object detection実装をする目的の上で、
自分が読んでいる中で役に立ったサイトのブクマ

object detection 参考記事ブックマーク

VoTT v2.1.0 を使用して画像のアノテーション（教師データの作成）を行う
https://qiita.com/clerk67/items/8e7207284037dcf1f9ec
用途：
json形式の出力データを確認したいとき



## TFレコード関連

TFレコードの簡易的な作り方を知る
https://daiiz.hatenablog.com/entry/2016/10/05/153727

TFレコードの読み取り方
https://nisshingeppo.com/ai/tfrecord-load/

tf.train.Exampleの構造について
https://nisshingeppo.com/ai/structure-tf-train-example/

LabelImgからTFレコードに変えるコード　Convert PASCAL dataset to TFRecord 
https://androidkt.com/convert-pascal-dataset-to-tfrecord-for-object-detection-in-tensorflow/

優先度低い　numpyからtfRecordに変えるコード
https://blog.shikoan.com/cifar-10-tfrecord/

## retina netはだいたいこれくらいでよし。
https://keras.io/examples/vision/retinanet/

retina netで使うtfRecordの形式について解説が下のほうにのってる
https://stackoverflow.com/questions/55021994/how-to-prepare-my-images-and-annotation-for-retinanet-training

keras_retina_netでの訓練の仕方
https://github.com/fizyr/keras-retinanet


# yolo
軽い扱い方
https://qiita.com/hkwsdgea_ttt2/items/ba352f6e5ef6032b5dc9

パラメータ集
https://qiita.com/shinya_sun_sun/items/8c368f3024bf5b0d14aa

暇な時見る記事
https://github.com/pjreddie/darknet/issues/728

# object detection
純粋に良記事
https://www.machinelearningnuggets.com/object-detection-with-tensorflow-2-object-detection-api/#image-segmentation-with-mask-r-cnn

日本語の記事の中ではよい
https://www.petitmonte.com/python/ai_cup_ramen.html


## 必要なfeature
```
'image/height': dataset_util.int64_feature(height),
  'image/width': dataset_util.int64_feature(width),
  'image/filename': dataset_util.bytes_feature(filename),
  'image/source_id': dataset_util.bytes_feature(filename),
  'image/encoded': dataset_util.bytes_feature(encoded_image_data),
  'image/format': dataset_util.bytes_feature(image_format),
  'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
  'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
  'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
  'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
  'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
  'image/object/class/label': dataset_util.int64_list_feature(classes),
```
【React】React Slickで詰まったとこ

# やりたいこと
* next.js、react-slickを使ってカルーセルを表示
![reactslick.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/7f315fe0-63fe-ef76-5ae5-e6bd80043842.gif)

# インストール
```react:パッケージ
npm install react-slick --save
```
```react:CSS
npm install slick-carousel
```

# 実装
```react:コンポーネント
import React from 'react';
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Image from 'next/image'

export default function Carousel() {
  const settings = {
    dots: true,
    autoplay: true,
    infinite: true,
    speed: 1000,
  };

  const images = [
    {
      id: 1,
      src: "/images/ファイル名.jpg",
      alt: "Image 1"
    },
    {
      id: 2,
      src: "/images/ファイル名.jpg",
      alt: "Image 2"
    },
    {
      id: 3,
      src: "/images/ファイル名.jpg",
      alt: "Image 3"
    }
  ];

   const imageStyle = {
     width: '100%'
   };
  
  return (
    <Slider {...settings}>
      {images.map((image) => (
        <div key={image.id}>
          <Image 
            src={image.src}
            alt={image.alt}
            width={500}
            height={500}
            style={imageStyle}
          />
        </div>
      ))}
    </Slider>
  );
}
```

```react:使用側
import Carousel from 'パス'

export default function Home() {
  return (
    <div>
      <Carousel />
    </div>
  );
}
```

:::note alert
間違えたポイント
**＜前提＞**
* Next.js使用
* 画像の保存先：public/images/**.jpg

パスは「public」以下から指定する。
相対パスの場合はimageの先頭に「/」を付ける

```diff_javascript
const images = [
    {
      id: 1,
-     src: "public/images/ファイル名.jpg",
+     src: "/images/ファイル名.jpg",
      alt: "Image 1"
    }
  ];
```
:::

:::note alert
間違えたポイント
* <Image />コンポーネントはwidthとheightを指定する必要がある。
* 100%にしたい場合は、別でスタイルを用意してやって、style={}としてあててやる。

```diff_javascript
const imageStyle = {
    width: '100%'
  };
  
<Image 
  src={image.src}
  alt={image.alt}
  width={500}
  height={500}
  style={imageStyle}
/>
```
:::

# エラー
* モジュールの宣言ファイルが見つかりません ～は暗黙的に'any'型になります。
プロジェクト作成時、TypeScriptを選択するとなるっぽい。

具体的な内容はキャプチャし忘れ。。。
```react
import Slider from "react-slick";
```
importにエラーの内容に記載されていたため、それ通りにコマンド実行



```react
npm i --save-dev @types/react-slick
```



# 参考文献
* 導入方法、よく使うコマンドが学べる。

https://qiita.com/Masanori_N/items/839a9b5a97decd564c6f

* コマンドが豊富

https://react-slick.neostack.com/

* 公式っぽいが分かりにくい

https://qiita.com/odennkunn/items/0a871d53450e6600d2d7

# バージョン
```react
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@next/font": "13.2.3",
    "@types/node": "18.14.6",
    "@types/react": "18.0.28",
    "@types/react-dom": "18.0.11",
    "next": "13.2.3",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-slick": "^0.29.0",
    "slick-carousel": "^1.8.1",
    "typescript": "4.9.5"
  },
  "devDependencies": {
    "@types/react-slick": "^0.23.10",
    "@types/slick-carousel": "^1.6.37",
    "autoprefixer": "^10.4.13",
    "postcss": "^8.4.21",
    "tailwindcss": "^3.2.7"
  }
```
Optimizerの出力にはTensorFlowの自動微分が効かない

とってもどうでもいい知見を得たのでメモ。

うまく微分できる例
```python
v = constant(3.0)
with GradientTape() as v_gt:
    v_gt.watch(v)
    y = v**2
    print(y)
    dfdv = v_gt.gradient(y, v)
    print(dfdv) # 6.0

```

```math
\frac{\partial f(v)}{h}=\frac{\partial f(v)}{\partial v}\frac{\partial v}{\partial h}
```
の$\partial v/\partial h$を計算したいのに、Kerasで用意されているOptimizerを挟むとうまく微分できなくなります。

うまく微分できない例
```python
v = Variable(3.0)
h = Variable(0.1)
opt = keras.optimizers.SGD(h)
opt.build([v])
dfdv = Variable(2.0)

with GradientTape() as h_gt:
    h_gt.watch(h)
    opt.update_step(dfdv,v)
    print(v)
    dvdh = h_gt.gradient(v,h)
    print(dvdh) # -2.0となってほしいのに実際はNoneになる
```
これは、KerasのOptimizerが、変数`v`の更新を破壊的操作によって行なっているからです。
うまく微分できる例では、`y`は`v`の計算によって誕生しているため、両者の関係性が繋がり、微分成分が生じました。しかし、この例では、`v`は`h`とは別の系統から誕生しているので、その後`v`にどのような処理がなされても、両者の関係性を繋げることができません。

実際、KerasのSGDのソースコードはこんな感じになっていて、変数に対して破壊的操作を施していることが分かります。
```python:sgd.py
variable.assign_add(-gradient * lr)
```
参考↓

https://github.com/keras-team/keras/blob/9de24b0beac97d1ef8c34e427beb895ef791d254/keras/optimizers/sgd.py#L185

TensorFlowでは、破壊的操作を通じて変数を演算しても、微分の成分は伝播されないようです。破壊的操作でも微分の成分が伝播されるように工夫できないんでしょうかね。

というわけで、$\partial v/\partial h=$更新後の変数に対するハイパーパラメータの勾配を計算するためには、「更新後の変数」が「ハイパーパラメータ」によって誕生している必要があるのです。
cloudwatch alarmのアクションを一括で変更する

cloudwatchアラームを止めたくてアクションを無効にしようとしたのだが、~~コンソールから無効は出来なかった。~~
現状CLIでしか出来ないみたい
なので以下コマンドで一括停止
```sh
aws cloudwatch describe-alarms | jq -r '.MetricAlarms[] | .AlarmName' | xargs aws cloudwatch disable-alarm-actions --alarm-names
```

再開したい時は以下を実行
```sh
aws cloudwatch describe-alarms | jq -r '.MetricAlarms[] | .AlarmName' | xargs aws cloudwatch enable-alarm-actions --alarm-names
```

## 追記: コンソールから出来るようになってた
対象のアラームを選択し、右上の `Actions` -> `Alarm actions - new` から有効・無効切り替えられるみたいです
Laravelの命名規則まとめ！


# はじめに
Laravelには、コントローラー、モデル、ビューなどの要素があり、それぞれに命名規則があります。また、Laravelはコーディング規約のPSR-1やコーディングスタイルのPSR-2に基づいた命名規則を採用しています。この記事では、Laravelの命名規則についてまとめていきます。

# Laravelの命名基本ルール

### 1. コントローラーの命名規則
コントローラーは、クラスで実装されます。コントローラーのクラス名は、以下のルールに従う必要があります。
- 単数形のパスカルケースで記述する。
- 「Controller」という接尾語を付ける。

また、一般的にコントローラー名には、アプリケーションのドメイン知識に関する単語を使用することが推奨されます。例えば、ECサイトの場合は`ProductController`や`CartController`などが該当します。

```php:ProductController.php
class ProductController extends Controller
{
    //
}
```
# 2. モデルの命名規則
モデルは、データベースとのやりとりを担当するクラスです。モデルのクラス名は、以下のルールに従う必要があります。
- 単数形のパスカルケースで記述する。

また、モデル名はテーブル名と一致するようにすることが推奨されます。例えば、product_namesテーブルに対応するモデルの場合は`ProductName`といった具合です。

```php:ProductName.php
class ProductName extends Model
{
    //
}
```

### リレーションの命名規則と記述方法
リレーションは種類に応じて、適切な記述方法を行います。例えば、`belongsTo`リレーションであれば、メソッド名を単数形のモデル名として定義します。
```php:Product.php
public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}
```
また、hasManyリレーションであれば、posts()のようにメソッド名を複数形のモデル名として定義します。
```php:User.php
public function products(): HasMany
{
    return $this->hasMany(Product::class);
}
```
# 3. マイグレーションファイルの命名規則
マイグレーションファイルは、データベースのテーブル構造を定義するためのファイルです。マイグレーションファイルのファイル名は、以下のルールに従う必要があります。

- 「create_テーブル名_table」という形式で記述する。
- 「xxx」の箇所には作成日時が入る。

例えば、「users」というテーブルを作成する場合は、以下のようにファイル名を記述します。
```
xxx_create_users_table.php
```

# 4. ビューの命名規則
ビューは、HTMLなどの表示用のファイルです。ビューのファイル名は、以下のルールに従う必要があります。

- ドットで区切られた単数形のスネークケースで記述する。
- ビューファイルの拡張子は「.blade.php」とする。

また、コントローラーと対応するビューの場合は、コントローラー名に対応したビュー名にすることが一般的です。例えば、`UserController`に対応するビューの場合は`user.blade.php`と命名します。

```
resources/
        views/
            user/
                user.blade.php
```

# 5. ルーティングの命名規則
ルーティングは、URLとコントローラーのアクションを紐付けるための設定です。ルーティングの名前は、以下のルールに従う必要があります。

- スネークケースで命名する。
- ルート名には、.（ドット）を使用する。

例えば、「Product」というコントローラーの「index」アクションに対応するルートがある場合は、以下のようにルートの名前を記述します。
```php:web.php
Route::get('products', [ProductController::class, 'index'])->name('product_name.index');
```

# まとめ
Laravelには、コントローラー、モデル、マイグレーションファイル、ビュー、ルーティングなど、様々な要素があります。命名規則は、プロジェクトのメンテナンス性や拡張性を高めるための重要な要素の1つですので、参考になれば幸いです。
TypeScriptで「固定長の配列」を再帰を使って宣言する方法

## はじめに

配列の長さを静的に決めておきたいことがよくあります。例えば9×9のリバーシの盤面を表現したい場合、長さ9の`number`（1マスの中の情報は`number`で表すとして）の配列を、9個用意することになり、そこからはみ出る参照は、実行前に取り除いておきたいものです。

```typescript
const board: [固定長配列の上手い型定義] = [[0,0,0,0,0,0,0,0,0], ... , [0,0,0,0,0,0,0,0,0]]

console.log(board[4][5]) // <- 0
console.log(board[9][0]) // <- 9×9の範囲を超えているので、コンパイル時にエラーが出るようにしたい
```

「長さ9の`number`の配列」は、TypeScriptの「タプル」を使えば、次のように表すことができます：

```typescript
const row: [number, number, number, number, number, number, number, number, number] = [0,0,0,0,0,0,0,0,0]
```

じゃあリバーシの盤面の型はこう？

```typescript
type Row = [number, number, number, number, number, number, number, number, number]
type Board = [Row, Row, Row, Row, Row, Row, Row, Row, Row]
```


…こんな汚ねえコードは書きたくねえ！！！！！ってことで、以下のよう **「固定長な配列」を「再帰」を使って表現**してみます：

## 結論

```typescript
type FixedLengthArray<T, N extends number, A extends any[] = []> = A extends { length: N } ? A : FixedLengthArray<T, N, [ ...A, T ]>
```

配列の要素の型引数 `T`, 配列の長さを表す型引数 `N`, 配列の蓄積を表す型引数 `A`に対して、[Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)を使って`A`が長さ`N`に達しているかどうか判定します。既に`N`に達していた場合はそのまま`A`を返せばよく、達していなかった場合は再帰的に`FixedLengthArray`を呼んで配列の蓄積の部分を引き伸ばしていくイメージです。

これを使えば、リバーシの盤面は次のように簡潔に表せますね！

```typescript
type Row = FixedLengthArray<number, 9>
type Board = FixedLengthArray<Row, 9>

// もしくはRowをかませず単純に
type Board = FixedLengthArray<FixedLengthArray<number, 9>, 9>
```

TypeScriptで、楽しい型パズルライフを送りましょう！

### 参考文献

https://stackoverflow.com/questions/41139763/how-to-declare-a-fixed-length-array-in-typescript
npmについて

# はじめに



#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>


# npmとは

Node Package Managerの意味で


Node.jsのパッケージを管理するシステムです。


パッケージの依存関係や競合関係を管理してくれます。



# npmの特徴


JavaScriptで書かれたプログラム。


npmはパッケージをインストールする際に各種ライブラリなどの依存関係を管理、パッケージの検


索や更新、バージョン管理、アンインストールなどもできます。


npmはNode.jsをインストールすると自動的にインストールされます。



# npmのメリットは？



元々npmはパッツケージのコードを複数プログラマでオープンソースで管理することが可能なように生成されている。


なので自身で制作しているコードをチームで共有しながら開発することが可能です。


### インストール、アンインストールが簡単
npmのインストールは
```terminal:terminal
$ npm install
```
と入力してコマンドを実行するだけで、簡単にパッケージをインストールすることができます。

アンインストールについても、
```terminal:terminal
$ npm uninstall
```
と入力してコマンドを実行するだけで簡単にアンインストールすることができます。



# まとめ



コマンドもいくつかあるので学習次第取り上げようと思います。
VSCodeのChatGPTで拡張機能のPrompt（質問文）をカスタマイズする（コードを書かない人編）






参考に記載の記事をお手本にしてVSCodeにChatGPTの拡張機能を追加したのですが、そもそもそんなコード書かないことに気が付きました。
デフォルトではコードレビュー関係のPrompt（質問文）のみが設定されていて、「～～について教えて！」のような内容をChatGPTに投げることができません。

なので、拡張機能の設定を変更し、コードレビュー以外の内容をVSCode上からChatGPTに投げるように変更しました。

# 設定変更内容

- 拡張機能の設定から、`Custom Prompt`を変更します。
  - デフォルトOFFなので、チェックをいれてONにします。
  - 設定したPromptに続いて選択範囲のテキストを投げる動作です。
    - 既定のPromptは「以下のコードについて～～」と設定されています。
  - `Custom Prompt1`は選択範囲の内容をそのまま投げます。
    - ブランクでは動作しなかったので、スペースを入力しています。
  - `Custom Prompt2`は選択範囲の内容をMarkdown書式で出力します。
    - `以下の質問の回答を、Markdown 記法でコピーアンドペーストできるようにコードブロックで出力して。`を設定しています。
    - 個人的によく利用するけど長文なものを設定しました。
  - `Custom Prompt`は2つまで設定出来ます。
  - `Custom Prompt`の表示名は変更出来ません。
  - デフォルトのPromptはチェックを外してみました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/ab2b4391-ee8e-3dc7-7cda-18db737bfeb0.png)




# 記載中に気が付いたこと

記載中に以下思ってしまいました…


- `Custom Prompt1`は`Ask a question`に質問文を入力すればいいのでは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/0ad38532-e482-5700-3234-51000284ccf1.png)

- `Custom Prompt2`は`ChatGPT: Export conversation`を使えばいいのでは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/7cde5806-49f8-c3ed-7983-c1397b57b0ea.png)




# 参考

https://qiita.com/tak001/items/c3000b3ce9b6e72b2ae5

https://qiita.com/akiraak/items/b8ad643eafe1a32341ff

https://marketplace.visualstudio.com/items?itemName=gencay.vscode-chatgpt
関数は数値じゃないですよって話

## 経緯

Rubyを学習していて、関数定義の部分でこんな記述に出会いました。
```
def hello
  'Hello'
end
```
こんなふうに書かれると、「これって関数自体が'Hello'って値を持ってるのか？だったら`return`とかつけずに、関数内でやることやって`break`して関数を引数にしちゃってもいいんじゃないか？」と思ったわけです。

## どう違うのか

天下のChatGPT様に聞いてみたところ、このような返答が来ました。

>関数自体が値を持っているというよりは、**関数が呼び出された時に'Hello'という文字列を返すように定義されています**。つまり、greeting関数が呼び出された結果として、'Hello'が返されるということです。

なので関数というのは、渡す値でも、返される値でもなく、その二つをつなぐ「橋」の部分なんですね。

大学で数学概論を受講したとき、集合の分野で **「写像」** という概念がありました。たしか写像の別名は **「関数」** じゃなかったか...
写像というのは、ある集合A, Bがあったときに、Aの要素にBの要素が対応するような関係のことをいいます。下図でいう矢印の部分に相当します。

詳しくは[こちら(写像 - Wikipedia)](https://ja.wikipedia.org/wiki/%E5%86%99%E5%83%8F)
![map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3114109/1b0ea003-dc72-92f1-0d7e-e7704487fb2f.png)

先ほどのコードに戻りましょう。

```
def hello
  'Hello'
end
```
この関数には、一見なんの引数も戻り値も無いように見えます。それは逆に言えば、「どんな値を渡されてもたった一つの値を返す」ということになります。全射っすね。

なのでこの関数は、写像的に言うと **「どんな値であっても"Hello"に対応させるような対応関係」** といえるわけです。

あっそうだ。Rubyの関数においては、`return`がなくても、自動的に戻り値が返されるようになっているようです。Rubyくんさぁ...

## まとめ
関数というのは、一見値を持つように見えても、それ自体は値を持ちません(持ってるものもあるかもしれないけど...)。
ある値を渡されて、それを別の値に対応づける(戻り値を返す)のが関数です。
初めてFinchを使用してみた！

# この記事について
Docker Desktopを使用している際
- アップデートをしても通知が消えない
- 起動・停止ができない

などの現象が起こっていたため、代わりとなるものはないか探していたところ、Finchというソフトウェアを発見しました。

- Docker Desktopの代替として期待されている
- かなり軽く、簡単にできる

という意見も多くあったので、お試し程度に見てみることにしました。


# Finchとは
2022年11月にAWSがオープンソースを公開したそうです。
詳しくは下記リンクに記載されています。

https://aws.amazon.com/jp/blogs/news/introducing-finch-an-open-source-client-for-container-development/


# 環境

今はMacOSのみサポートしています。
今後はWindowsとLinuxにも対応する予定らしいです。
### 使用環境
```
MacOS Big Sur: version 11.5.1
```


# 内容
### インストール
brewコマンドでインストールします。
```
brew install --cask finch
```
下記リンクからダウンロードも可能です。

https://github.com/runfinch

パスワードを入力した後、
`
🍺  finch was successfully installed!
`
このような表示が出て、インストールできました。

### 初期設定＆起動停止
Finchの仮想マシン（VM）を利用するには初期設定する必要があるので、下記のコマンドを叩きます。

```
finch vm init
```
これで今後同じコマンドを叩かなくても、自動的にVMが起動されます。

2回目以降の起動・停止は下記のコマンドになります。
```
finch vm start
finch vm stop
```

`
Finch virtual machine started successfully
`
このような表示が出たらOKです

### Hello Finch
準備が完了したので、とりあえず公式が用意してくれている簡単なコンテナを起動してみます。
```
finch run --rm public.ecr.aws/finch/hello-finch
```

読み込みが終わるとfinchのマークが表示されました！
```

                            @@@@@@@@@@@@@@@@@@@                                 
                        @@@@@@@@@@@@    @@@@@@@@@@@                             
                      @@@@@@@                  @@@@@@@                          
                    @@@@@@                        @@@@@@                        
                  @@@@@@                            @@@@@                       
                 @@@@@                      @@@#     @@@@@@@@@                  
                @@@@@                     @@   @@@       @@@@@@@@@@             
                @@@@%                     @     @@            @@@@@@@@@@@       
                @@@@                                               @@@@@@@@     
                @@@@                                         @@@@@@@@@@@&       
                @@@@@                                  &@@@@@@@@@@@             
                 @@@@@                               @@@@@@@@                   
                  @@@@@                            @@@@@(                       
                   @@@@@@                        @@@@@@                         
                     @@@@@@@                  @@@@@@@                           
                        @@@@@@@@@@@@@@@@@@@@@@@@@@                              
                            @@@@@@@@@@@@@@@@@@


Hello from Finch!

Visit us @ github.com/runfinch
```

# 参考記事
[AWSが「Docker Desktop」代替となり得る「Finch」をオープンソースで公開　ローカルマシンに仮想環境・ビルドツールなど一式を導入](https://www.itmedia.co.jp/news/articles/2211/24/news107.html)

[Docker Desktopの代わりに「Finch」を使ってみる - とことんDevOps | 日本仮想化技術が提供するDevOps技術情報メディア](https://devops-blog.virtualtech.jp/entry/20230206/1675651483)

[Finch使ってみた - finchコマンドはほぼdockerやdocker-composeコマンドとして利用できた - Qiita](https://qiita.com/yokawasa/items/d49c5b4614ab929654a4)

[DockerDesktopの代替になるかも？と巷で話題の「Finch」を使ってみた - NRIネットコムBlog](https://tech.nri-net.com/entry/use_finch)
laravel-mixでAPP_ENVごとに読み込む.envを変更する

Laravelで環境ごとの.envファイルを
.env.local
.env.staging
.env.production

と分けたりすると思うんですが
このLaravel側の.envを
js側でも***環境に応じて***読み込みを変えていきたい場合の対応法です

## 前提条件
- docker-composeでAPP_ENVを定義している(local/staging/production)
- Laravelで下記のような.envファイルが環境ごとに存在する
    - .env.local
    - .env.staging
    - .env.production
- laravel-mixでwebpackのビルドステップを定義している

## 対応方法

1. dotenvとdotenv-expandをnpm install
1. webpack.mix.js に下記を追記
    ~~~js:webpack.mix.js
    const dotenvExpand = require('dotenv-expand');
    dotenvExpand(require('dotenv').config({path: `./.env.${process.env.APP_ENV}`}));
    ~~~
1. 読み込みされていることを確認
    ~~~js:_env.js
    const env = {
      studiounbuilt_url: process.env.MIX_STUDIOUNBUILT_URL,
    }

    export default env
    ~~~

# 最後に
js環境構築周りナニモワカラナイと言って数年経ってます。
laravel-mixはもう卒業した方がいい気もしている。

---
私はバックエンドをめっちゃ頑張るので
一緒に働いてくれるフロントエンジニアを募集しています。


↓興味のある方はこちらから↓
[Wantedly - スタジオアンビルト株式会社](https://www.wantedly.com/companies/studiounbuilt)

こんなWebサービスを作っています。
・[マドリー](https://madree.jp/)
・[Studio Unbuilt](https://www.studiounbuilt.com/)
git fetchでつまづいた素人の備忘録

## 発生した問題

https://eng-entrance.com/git-fetch

上記などを参考にしつつ、一人でプルリクエスト練習中にリモートブランチを更新してローカルに取り込む部分で、ファイルが更新されていない問題に出くわしました。



```:リモートをfetchを実行
$ git fetch origin
```



## 解決策

https://stackoverflow.com/questions/9841433/git-fetch-doesnt-update-my-local-repository

下記記事で `origin/main` と `main` ブランチのhead違いを確認してみろとあったので確認しました。

```:origin/main
$ git log origin/main | head
commit b0615378c8cb327cbc5fafb3f6454b6c52730c40
Merge: 35cd328 dafd45e
Author: kabokawakabo <62997698+kabokawakabo@users.noreply.github.com>
Date:   Mon Mar 13 10:46:03 2023 +0900

    Merge pull request #2 from kabokawakabo/tmp
    
    Tmp環境をmainにマージ依頼

```

```:main
$ git log main | head
commit 35cd3287c2fe825780b38482a059277d039a2fb3
Merge: 27b8da0 354aec2
Author: kabokawakabo <XX@XXMacBook-ea.local>
Date:   Sat Feb 11 14:49:20 2023 +0900

    Merge remote-tracking branch 'origin/main'

commit 27b8da03d5dd8741116fc74193df91b0a5f66463
Author: kabokawakabo <XX@
XXMacBook-ea.local>
```

###### HEADが違う！

-- --
その後、同じ記事を参照しつつ、実行しました。（今回は`origin/main`側に ローカルのmainのHEADを揃える）

- 注意：一番下に本当にしたかったコマンドがあります。



```:origin/mainと同じ位置の new_mainのブランチを作成し移動
$ git checkout origin/main -b new_main
```

```:mainに移動
git checkout main
```

```:mainを new_mainにマージ
git merge new_main
```

この方法だと new_mainのブランチが残ってしまったので `$ git branch -d new_main` で削除しました。

## 補足
結局上記コマンドは以下のコマンドでOKだったと思います。
```:mainヘッダー を origin/main に揃える
$ git checkout main
$ git merge origin/main
```

よくよく考えたら、 リモートの設定（ローカルのorigin/~ が指す）を`fetch` して ローカルのブランチに `merge` するという考えなので、 mergeしてないのにファイルが変わってないと焦っていた自分が恥ずかしいですね...。失敗してもいい時に勉強になったのでヨシ！ということで


-- --
どうでもいい独り言

「mergeのコマンドを上手く使えば、1ラインで書けそうだと思ったのですが、前・後でmergeしたいbranch書き間違えてミスってしまう人的災害?を防ぐために、各実行を適宜するやり方がデフォルトで採用されているのかもと思ったりしました」
PowerVSのイメージをICOSにエクスポート・インポートする際のソースIPアドレス

PowerVSには、イメージをユーザーのICOS Bucketにエクスポート、インポートする機能があります。
https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-capturing-exporting-vm

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/c39a782d-2325-4f88-ce03-780c8f3ddbd4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/cdfef25c-99d0-ce84-b19a-a37aaa785117.png)

セキュリティの観点でユーザーがICOS側のFirewall機能を使って送信元IPアドレスを絞っている場合、PowerVS側のソースIPアドレスが何になるかDocsには記載がないため、何を許可すればよいか分かりません。

PowerVSからのアクセスがICOS側Firewallでブロックされると、下記のようなエラーがでます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/312d711d-6c71-59c7-b854-bbbeefa63a0a.png)

```
Error
Failed to export the boot image tmgw-tier1-image, verify your cloud storage resource and access information and retry the operation
```


下記の方法でPowerVS側の送信元IPを確認できます。

ICOSへのアクセスログを確認したいので、ICOSのbucket設定で、Activity Trackerにログを書き出す設定にします。
データイベントも取得するようにします。
（ログからIPアドレスを確認する目的なので、確認が終われば、Activity Trackerの設定は無効にしても構いません）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/a49119a6-8cf8-776d-a14b-7ac537d35b35.png)

その状態で、PowerVSからICOSにイメージのExportを実施。

Activity Trackerにイメージ書き込みのログが記録され、その中にソースIPアドレスの情報が含まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/e2f838d6-55eb-4483-9bab-5f2d612af2d7.png)

このIPアドレス範囲をICOSのFirewallに設定すれば、送信元を絞った状態でPowerVSからイメージのエクスポート、インポートを行えます。
ソースになるサブネットはロケーションによって異なるため、/26等、細かく絞りたい場合は実機で確認する必要がありますが、10.0.0.0/8を指定可能であれば、ロケーションによらず許可できます。

ご参考にTOK04のPowerVSの場合は10.192.119.128/26、OSA21のPowerVSの場合は10.8.15.128/26が接続元になるようです。
（変わる可能性は少ないとは思いますが、不変が保証されている訳ではない点、ご留意ください。）

以上
WSLでpythonを使ってmp3を再生する

WSLで音を鳴らしたいときはffmpegとpydubを使いましょ。めっちゃ簡単に鳴らせます。

```sh
sudo apt install ffmpeg
pip install pydub
```

```py
from pydub import AudioSegment
from pydub.playback import play

sound = AudioSegment.from_mp3("./music.mp3")
play(sound)
```
さくらのレンタルサーバにNextJSアプリをデプロイ

## やりたいこと
仕事用に自由に使えるサーバとドメインの確保目的で契約している
さくらのレンタルサーバ（スタンダードプラン）に、
自作したReactやNextJSのWebアプリをデプロイしたい。

## 大まかな流れ
* NextJSでWebアプリ作成
* npm run build で公開用のファイルを生成
* さくらサーバへ転送
* 公開

## NextJS でWebアプリを作成
まぁ普通に作成、React-Three-Fiber でアイコンをグリングリン回すようなものでヨシ！

ファイルパスの相対パス化のために `package.json` に以下の項目を追加
```diff_json:package.json
{
  "name": "hogehoge",
  "version": "0.1.0",
  "private": true,
+  "homepage": "./",
  "scripts": {
```

## npm run build
Reactでは `npm run build` で `./build` 以下にファイルが生成されるのですが、
NextJSでは `next export` という処理も必要だそうです。
また出力先も`./out` になります。

というわけで、`package.json` のスクリプトに以下のものを追加しました。

```diff_json:package.json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
+    "export": "next export",
    "start": "next start",
  },
```

そして、`npm run build` からの `npm run export` で、
デプロイ用のファイル群が生成されます。

とここまで書いて、気がついたのですが、スクリプト１つで良いですね。


```diff_json:package.json
  "scripts": {
    "dev": "next dev",
-    "build": "next build",
+    "build": "next build && next export",
    "start": "next start",
  },
```
これで、`npm run build` 一発で生成されました。

## さくらサーバへ転送
`./out` 以下をzipで圧縮して転送しても良いですが、scp -r でそのまま送ります。

```console
bash-3.2$ scp -r ./out user_name@sakuraServer:~
 :
```

## 公開
さくらサーバにログインして、先ほどホームディレクトリに転送した`./out` を、
`~/www/` 以下の適当なところに`mv`で移動します。

```console
bash-3.2# ssh user_name@sakuraServer
user_name@sakuraServer's password:
Last login: Mon Mar 13 10:23:12 2023 from ****
FreeBSD 13.0-RELEASE-p12 (GENERIC) #0: Tue Sep 12 19:33:31 UTC 2023

Welcome to FreeBSD! 
```
### やっぱいいですね、FreeBSD、がんばれ BSD! Linuxなんかに負けるな！！
あ、ついつい心の声がっ！

## 最後に
作業自体は、大した作業ではないし、ネット上ですぐに見つかる情報ですが、
どうせまた絶対に忘れるので、自分のところに備忘録的に記しました。

古い人間なので、AWS Amplify とか Firebase みたいなサーバレスより
自分でログインして普通に使えるサーバが安心できちゃいます。
オールドタイプです。
sharepoint サイトid 確認方法

ブラウザに
https://<tenant>.sharepoint.com/sites/<site-url>/_api/site/id
入力すれば、出てきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/fc64c627-243f-5dad-e01b-edce1b0fa1c1.png)
dataverse xrm tool  nullを保存する方法

CrmFieldType.Rawを使って、カラムをnullに更新可能。
new CrmDataTypeWrapper(null, CrmFieldType.Raw)


    // Create an account record  
    Dictionary<string, CrmDataTypeWrapper> inData = new Dictionary<string, CrmDataTypeWrapper>();  
    inData.Add("name", new CrmDataTypeWrapper("Sample Account Name", CrmFieldType.String));  
    inData.Add("address1_city", new CrmDataTypeWrapper("Redmond", CrmFieldType.String));  
    inData.Add("telephone1", new CrmDataTypeWrapper("555-0160", CrmFieldType.String));  
    accountId = ctrl.CrmConnectionMgr.svc.CreateNewRecord("account", inData);  
  
    // Verify if the account is created.  
    if (accountId != Guid.Empty)  
    {  
        Console.WriteLine(“Account created.”);  
    } 


# 参考サイト
https://community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/166394/xrm-tooling-update-pick-list-value-to-null
c# EPPlusの使い方

EPPlus version 5以降は、有料になるので、
普通の開発は、EPPlus version ４で良いかと思います。

# Excelファイル作成
```
class Program
{
    static void Main(string[] args)
    {
        // 出力ファイルの準備（実行ファイルと同じフォルダに出力される）
        FileInfo newFile = new FileInfo("result.xlsx");
        if (newFile.Exists)
        {
            newFile.Delete();
            newFile = new FileInfo("result.xlsx");
        }
 
        // Excelファイルの作成
        using (ExcelPackage package = new ExcelPackage(newFile))
        {
            // ワークシートを1枚追加
            ExcelWorksheet sheet = package.Workbook.Worksheets.Add("シート名");
 
            // A1セルに書き込み
            sheet.Cells["A1"].Value = "Hello World";
 
            // セルはR1C1形式でも指定可
            sheet.Cells[2, 1].Value = 27;
 
            // 保存
            package.Save();
        }
    }
}
```
# 枠線色設定

```
//枠線色をグレーにして、線を細くする
sheet.Cells[2, 1].Style.Border.BorderAround(ExcelBoderStyle.Thin,ColorTranslator.FromHtml("#7f7f7f"));
```

# セル背景色設定
```
sheet.Cells[2, 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
sheet.Cells[2, 1].Style.Fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#7f7f7f"));
```

# 文字列中央揃え
```
sheet.Cells[2,1].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
```
# セル結合
```
sheet.Cells[2,1,2,4].Merge = true;
```

# 参考サイト


https://chawatoyo.blog.fc2.com/blog-entry-6.html
[AWS Q&A 365][S3]Daily Five Common Questions #3

# 1. What is IAM Access Analyzer and how can it help me validate policies?
Answer: IAM Access Analyzer is a tool provided by AWS that helps you validate policies and ensure they conform to security best practices. You can learn more about it in the IAM User Guide.

# 2. What compliance programs does Amazon S3 participate in?
Answer: Amazon S3 participates in multiple AWS compliance programs, including System and Organization Controls (SOC), Payment Card Industry Data Security Standard (PCI DSS), Federal Risk and Authorization Management Program (FedRAMP), and Health Insurance Portability and Accountability Act (HIPAA).

# 3. How can I assess the compliance of my Amazon S3 resources?
Answer: AWS provides several resources to help you assess the compliance of your Amazon S3 resources, including Security and Compliance Quick Start Guides, Architecting for HIPAA Security and Compliance, AWS Compliance Resources, AWS Config, and AWS Security Hub.

# 4. How can S3 Object Lock help me meet regulatory requirements for data storage?
Answer: S3 Object Lock can help you meet the technical requirements of financial services regulators (such as the SEC, FINRA, and CFTC) that require write once, read many (WORM) data storage for certain types of books and records information.

# 5. Can I access Amazon S3 resources from my applications?
Answer: Yes, customers are able to access Amazon S3 resources from their applications, for example, from a JavaScript XMLHttpRequest object.
[AWS Q&A 365][S3]AWSのよくある問題の毎日5選 #3

# 1. IAM Access Analyzerとは何ですか？どのようにポリシーを検証するのに役立ちますか？
IAM Access Analyzerは、AWSが提供するツールであり、ポリシーを検証してセキュリティのベストプラクティスに準拠していることを確認するのに役立ちます。IAMユーザーガイドで詳細を学ぶことができます。

# 2. Amazon S3はどのようなコンプライアンスプログラムに参加していますか？
Amazon S3は、システムおよび組織のコントロール（SOC）、ペイメントカード業界データセキュリティ基準（PCI DSS）、連邦リスクおよび認可管理プログラム（FedRAMP）、および健康保険の携帯性および責任法案（HIPAA）を含む、複数のAWSコンプライアンスプログラムに参加しています。

# 3. Amazon S3リソースのコンプライアンスをどのように評価できますか？
AWSは、セキュリティとコンプライアンスのクイックスタートガイド、HIPAAセキュリティとコンプライアンスの設計、AWSコンプライアンスリソース、AWS Config、AWS Security Hubなど、複数のリソースを提供して、Amazon S3リソースのコンプライアンスを評価するのに役立ちます。

# 4. S3 Object Lockは、データストレージの規制要件を満たすためにどのように役立ちますか？
S3 Object Lockは、一部のブックとレコード情報の特定のタイプに対して、一度書き込み、多数回読み取り（WORM）データストレージを要求する金融サービス規制当局（SEC、FINRA、CFTCなど）の技術要件を満たすのに役立ちます。

# 5. アプリケーションからAmazon S3リソースにアクセスできますか？
はい、お客様は、例えばJavaScriptのXMLHttpRequestオブジェクトからAmazon S3リソースにアクセスすることができます。
【PHP/Laravel】Carbonで想定通りの日時にならない！どうする？

# はじめに
Laravelには、日付や時刻を扱う処理を簡単にしてくれる**Carbon**という便利なライブラリが標準で備わっています。

この**Carbon**を使う上でハマりがちな落とし穴があるので、その例を示して確認していきます。

# 想定読者
PHP/Laravel初学者

# 開発環境・前提

### 開発環境
- OS：Windows11 22H2
- PHP 8.2.0
- Laravel 9.44.0

### 前提
- ローカルにLaravel開発環境があること。

（準備）
作成済みのLaravelプロジェクトのルートディレクトリまでコマンドラインで移動し、コマンド`php artisan tinker`でTinkerを起動。

※Tinker：Laravelに標準搭載されている対話型の実行環境

### Tinkerでの確認手順
①まずは以下の通りに、各内容を一つずつ順番に入力していきます（「>」の後ろの内容）。

```md:Tinker
> use Carbon\Carbon;

> $now = Carbon::now();
```

下の画像のように変数`$now`に現在の日時が代入されます。
![Tinker_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512880/b2ca32a7-ae3e-2292-fcac-ed819198a78d.png)
②次に以下のように入力すると、画像のように先程`$now`に代入した日時から5時間経過した日時が、変数`$afterFiveHours`に代入されます。

```md:Tinker
> $afterFiveHours = $now->addHours(5);
```
![Tinker_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512880/9d7bae16-df0d-aad3-ba57-e51060b64d18.png)
③この後、`$now`から7時間後の日時を変数`$afterSevenHours`に代入します。

```md:Tinker
> $afterSevenHours = $now->addHours(7);
```

![Tinker_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512880/062a8717-0623-ed77-15fd-1e6f322964cf.png)
おかしいですね…
この例では`$now`には`2023-03-08 16:23:12`という日時が代入されているので、その7時間後だと16時+7時間で23時になるはずです。

ではどうして想定通りの日時にならないのでしょうか？

…

ズバリ、②の過程で元の`$now`の日時が16時から21時に上書きされてしまったからです！
これにより、③の過程で16時だと思って使用した`$now`が実は21時であり、そこから7時間後の4時になったのです。

しかし感覚的には`$now`を16時の状態で保持したまま、最終結果は23時にしたいところです。
それでは一体どうすれば良いのか？

…

次のようにすれば、一瞬で解決できます！

```md:Tinker
> use Carbon\CarbonImmutable;

> $now = CarbonImmutable::now();

> $afterFiveHours = $now->addHours(5);

> $afterSevenHours　= $now->addHours(7);
```
![Tinker_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512880/7dee073b-7d01-73ab-7fbf-3d8f9247da6f.png)
先程は`use Carbon\Carbon;`としていたところを`use Carbon\CarbonImmutable;`に変更しています。
これで元の`$now`の日時が変わることなく、5時間後および7時間後の日時を正しく求めることができます。
`Carbon`の代わりに`CarbonImmutable`を使うだけで良いので、簡単ですね！
（ちなみにimmutableは「不変の」という意味なので、まさに文字通りです！）

# おわりに
**Carbon**を使っているとハマりがちのポイントなのでご注意ください！
複数人で開発する際は、日時の扱いについて事前に共通認識を持っているとスムーズに進められると思います。

本記事が少しでも読者の皆様の参考になれば幸いです。
それでは良き開発ライフを！！

# 参考情報
- Tinkerについて
Tinker（REPL）の項を参照

https://readouble.com/laravel/9.x/ja/artisan.html


- Carbonについて

https://carbon.nesbot.com/docs/


- Laravel Daily様のYouTubeでの解説動画
英語での解説ですが、動画を見ているだけで内容を把握できるぐらい分かりやすいです。
本記事はこの動画の内容と同じことを行っています。

https://youtu.be/npdotV1JZyc
Next.jsとTypescriptとtailwindを組み合わせた開発環境をつくりたい

Next.js、TypeScript、Tailwind CSSを組み合わせた開発環境を構築する基本的な手順を紹介します。

# 1.Node.jsとnpmをインストールする
最初に、Node.jsとnpmをインストールする必要があります。npmは、パッケージ管理システムであり、Node.jsと一緒にインストールされます。詳しいインストール方法については、Node.jsの公式サイトを参照してください。

# 2.Next.jsプロジェクトを作成する
ターミナルで、以下のコマンドを実行して、Next.jsプロジェクトを作成します。

```lua
npx create-next-app my-app --example with-typescript
```

このコマンドは、TypeScriptを使用したNext.jsのサンプルアプリケーションをダウンロードし、新しいプロジェクトを作成します。my-appは、プロジェクトの名前を指定する部分であり、任意の名前を指定できます。

# 3.Tailwind CSSをインストールする
ターミナルで、以下のコマンドを実行して、Tailwind CSSをインストールします。

```csharp
npm install tailwindcss
```

# 4.Tailwind CSSの設定を追加する
Tailwind CSSを使用するには、設定ファイルを作成する必要があります。ターミナルで、以下のコマンドを実行して、設定ファイルを作成します。

```csharp
npx tailwindcss init
```

これにより、tailwind.config.jsファイルが作成されます。このファイルには、Tailwind CSSの設定が含まれます。

# 5.CSSファイルを作成する
Next.jsでは、CSSファイルをグローバルにインポートする必要があります。ターミナルで、以下のコマンドを実行して、CSSファイルを作成します。

```bash
touch styles/globals.css
```

次に、globals.cssファイルに、以下のコードを追加します。

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

これにより、Tailwind CSSのスタイルがグローバルに適用されます。

# 6.Next.jsの設定を変更する
最後に、Next.jsの設定を変更して、TypeScriptとTailwind CSSを使用できるようにします。まず、以下のコマンドを実行して、必要なパッケージをインストールします。

```lua
npm install --save-dev typescript @types/react @types/node postcss-preset-env postcss-flexbugs-fixes
```

次に、プロジェクトのルートディレクトリに、以下のpostcss.config.jsファイルを作成します。

```js
module.exports = {
  plugins: [
    "tailwindcss",
    "postcss-flexbugs-fixes",
    [
      "postcss-preset-env",
      {
        autoprefixer: {
          flexbox: "no-2009"
        },
        stage: 3,
        features: {
          "custom-properties": false
        }
      }
    ]
  ]
};
```

これにより、PostCSSと必要なプラグインを設定し、Tailwind CSSを使用できるようになります。

最後に、tsconfig.jsonファイルを更新して、TypeScriptの設定を変更します。以下のコードを追加します。

```json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["components/*"],
      "@/styles/*": ["styles/*"]
    }
  }
}
```
これにより、コンポーネントやスタイルのインポート時に、エイリアスを使用できるようになります。

以上で、Next.js、TypeScript、Tailwind CSSを組み合わせた開発環境の設定が完了しました。これらの技術を使って、Webアプリケーションを開発することができます。

# 7.プロジェクトを起動する
最後に、以下のコマンドを実行して、プロジェクトを起動します。

```lua
npm run build
npm run dev
```

これにより、開発用のサーバーが起動し、ブラウザでアプリケーションを確認できるようになります。

以上で、Next.js、TypeScript、Tailwind CSSを組み合わせた開発環境の構築が完了しました。必要に応じて、その他のパッケージやライブラリをインストールして、開発を進めていくことができます。
Google AdMobで「コンテンツの前面に重なって表示される Google が配信する広告の扱い」という問題が検出された時の対処方法

# 発生した問題
先日、個人で開発しているアプリに対して
`お客様のアプリへの Google AdMob 広告配信に制限がかけられました`
というタイトルのメールが届きました。
![スクリーンショット 2023-03-12 15.40.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/a00771bb-172e-f4a8-0d38-c3f6e36811b7.png)

広告を掲載するようにして2年くらい経つのですが、今まで問題なく運用できていたのに急にこのようなメールが届いたため少し焦りました。

# 対応方法
## 違反内容の確認
AdMobの管理画面から問題の内容を確認してみたところ、
`コンテンツの前面に重なって表示されるGoogleが配信する広告の扱い`
が問題となっていたようです。
![スクリーンショット 2023-03-12 8.56.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/feb735dd-b52e-8f34-4c4b-b88d5e351736.png)

もう少し詳細を確認してみたところ、下図のように、Google 広告がコンテンツの前面に重なって表示されるように Google 広告コードを配置しているてはいけないようです。
![スクリーンショット 2023-03-12 15.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/fc155dab-bf8a-9be0-8c0d-d8a70d663e2c.png)

こちらを参照：[コンテンツの前面に重なって表示される Google が配信する広告の扱い](https://support.google.com/publisherpolicies/answer/11127388?hl=ja#zippy=%2C%E3%81%93%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E5%88%B6%E9%99%90%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%83%92%E3%83%B3%E3%83%88)

## アプリの現状確認
自分のアプリを確認してみたところ、下図のように、`ARSCNView`上に広告を配置していました。
ばっちりポリシー違反してますね。。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/cdb793f2-ac42-a228-eaf7-4988f79dffdb.png" width=50%>

## アプリ側の修正
そこで下図のように、`ARSCNView`の下に広告を配置し、広告がコンテンツの前面に重なって表示されないようにしました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/41724f41-d24f-3d05-ad76-ced8b8e7c201.png" width=50%>

修正が完了したら、いつも通りアプリを審査に提出し、リリースします。

## AdMobの対応
先ほどのAdMobの管理画面から、「審査をリクエスト」をクリックし、どのように修正したかを具体的に記載します。
自分の場合は、下記のように記述しました。
```
ARSCNViewと広告の配置を修正し、広告がARSCNViewに重なって表示されないようにしました。
```
記入が完了したら、「リクエストを送信」をクリックし完了です。
（審査には少し時間がかかる場合があるようです。）

![スクリーンショット 2023-03-12 8.55.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/40337e6e-9e3a-9a47-bbd4-3942c9ae8416.png)


# 結果
リクエストを送信した翌日、
`Google AdMob ポリシー違反に関する審査について`
というメールが届き、下記のような内容が記載されていました。
```
お客様のアプリにポリシー違反は見受けられませんでしたが、広告配信が一時的に制限されている場合、再度広告が表示されるまでに少々時間を要することがございます。どうぞご了承ください。
```
![スクリーンショット 2023-03-13 10.34.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/31d4771f-ed7f-21e6-ea34-26d4f8aacdce.png)

また、AdMobの管理画面から「ポリシーセンター」を確認しても、以前の問題は記載されていませんでした。
![スクリーンショット 2023-03-13 10.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91285/f8516945-535e-881a-73a4-2aaa5b81134f.png)


アプリを確認したところ、無事広告が掲載されていました :tada:

# まとめ
ガイドラインを正しく理解した上でAdMobを利用しましょう。（反省）
scpよりもrcloneの方が優れているというお話

# 対象読者
以下の人が対象です。

* 大量ファイルの転送に困っている人
* リモート・ローカル間のファイルのやり取りに悩んでいる人

研究室の後輩やHPCを利用している人がscpを使っていて、上記のような問題で困っていることが多かったのに耐えられず書きました。

# rclone

https://rclone.org/

> Rclone is a command-line program to manage files on cloud storage. It is a feature-rich alternative to cloud vendors' web storage interfaces. Over 40 cloud storage products support rclone including S3 object stores, business & consumer file storage services, as well as standard transfer protocols.

Rcloneはクラウドストレージ上のファイルを管理するためのコマンドラインプログラムです。クラウドベンダーのWebストレージインターフェースの代替手段として、豊富な機能を持ちます。40以上のクラウドストレージ製品（e.g. S3のオブジェクトストアやビジネス・消費者向けファイルストレージサービス）がrcloneをサポートし、標準的な転送プロトコルとしても機能します。

## よく使う機能
私は以下のような機能を主に使ってます。

1. sftpを用いたリモート/ローカル間の差分ファイル転送
2. リモートディレクトリのマウント

これに加え、クラウドストレージも通常のリモートディレクトリと同じように扱えるのがrcloneのすごい所。
今回は、上の二点の機能について導入と使い方を解説します。

## sftpを用いたリモート/ローカル間の差分ファイル転送
```
Usage:
  rclone copy source:path dest:path [flags]
```
ソースとデスティネーションにはscpコマンドと同じ要領でパスを指定します。
ただし、`rclone config`（後述）でホスト名のエイリアスを作成する必要があります。

::: note
`rclone copy`はファイルの差分を見てコピーしているので、中途再開で時間の節約ができます。
また、セキュアなファイル転送プロトコル（sftp）を用いているので安心感があります。
:::


## リモートディレクトリのマウント
```
Usage:
  rclone mount remote:path /path/to/mountpoint [flags]
```
::: note alert
オプション`--vfs-cache-mode writes`を付けないと、ファイルを編集したときに怒られます。
:::

一応、誤解を広めないために付け加えておくと、VSCodeにもリモートディレクトリをマウントできる機能はあります。`rclone mount`の場合、ファイルの編集が反映されるまでに数秒のラグが生じるデメリットがあります。


# rcloneの使い方

https://rclone.org/downloads/

上のリンクから自分の環境にあったバイナリをダウンロードしてください。rcloneが存在するディレクトリにPATHを通したら`rclone config`で初期設定をします。ローカル環境がWindowsでsftpを使う場合は、chocoなどのパッケージマネージャを通して[WinFsp](https://winfsp.dev/)を事前にインストールしてください。

まず、こんな画面が出てきます。
```
Current remotes:

Name                 Type
====                 ====

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q>
```

CLI上でインタラクティブな設定操作ができるのが、rcloneの大きな特徴。
日本語には対応していないですが、ユーザ名やアクセストークンなどを手順通りに設定すれば大丈夫です。
sftpだと4つくらい設定項目があります。
```
Configuration complete.
Options:
- type: sftp
- host: ************
- user: foouser
- pass: *** ENCRYPTED ***
Keep this "hogehost" remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d> y
```

これにて設定完了。

# scpとrcloneの違い
||scp| rclone|
|:--|:-:|:-:|
| リモート/ローカル転送 |✅|✅| 
|暗号化通信|✅|✅|
| 差分コピー ||✅|
| クラウドストレージ対応 ||✅|
|ディレクトリのマウント||✅|
|OS対応状況|ほぼ全部|ほぼ全部|


大容量のファイル（1TB）をリモートにアップロードする時に、差分コピーができる機能はとても重宝します。
余談ですが、組織のポリシーでrsyncのポートが禁止されている可能性があるので、rcloneはrsyncの代替手段にもなり得ます。（rsyncのようにファイルサーバを立ち上げる機能はrcloneにはありません。）
 
# まとめ
scpよりもrcloneの方が多機能で安全なので、rcloneを使ってファイル転送で楽をしましょう。
`rclone copy`と`rclone mount`を覚えておけばそんなに困りません。
Microsoft FormsとPower Automateを使って、アンケート結果からランダムに一つ取得してTeamsに投稿するアプリを作ってみた（追加機能編）

前編・後編で一通りの処理を作成しました。

前編はこちら：https://qiita.com/flutter_daisuki/items/a33fb58283d3780830e8
後編はこちら：https://qiita.com/flutter_daisuki/items/5dfa11d0bb83d57f021a

今回は追加機能として、テーマの数が減ってきた・もうなくなってきた時にリマインドとして、
チームメンバーにテーマをさらに投稿してもらうためのメッセージをチャネルに投稿する機能を作っていきます。
処理はいたって簡単です。

## 目的
グループメンバーがフォームから投稿したテーマの中からランダムで一つ取得して、MTG前にチャネルに投稿してくれるアプリを作りたい

## 背景
会社では毎週決まった時間に所属グループ全員が集まるMTGがあり、そこで3,4人に分かれたブレイクアウトルームを作り、
コミュニケーションを取る時間を設けています。
毎週グループリーダーがその場でテーマを決めるのは大変なので、メンバーから募集を募ることにしました。
そこで、メンバーにはフォームから自分が考えたテーマを投稿してもらい、集まったテーマ一覧の中からランダムに一つピックアップして、MTG時間に投稿してくれるようしたいと思います。


## 使う技術・ツール
【１】Microsoft Forms
　→ メンバーがテーマを投稿するためのフォームを作るのに使います

【２】Power Automate
　→ 投稿されたテーマをSharePointリストに追加する処理と、Teamsのチャネルに自動投稿する処理に使います。

【３】Microsoft Teams
　→ ここのチャネルに選ばれたテーマを投稿するようにします

【４】Share Point
　→ Formsから取得したテーマをリストに保存するのに使います

## 実装
#### ５、集まったテーマの数が残りわずかになった時に、再度投稿してもらうためのメッセージをチャネルに投稿
前回まで作ってたワークフローの続きに書いていきます。

まずは新しいステップをクリックして、検索エリアに「コントロール」と入力し、「**条件**」を選択します。
![スクリーンショット 2023-03-11 16.26.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/5410d0b1-dbcd-6e36-e82a-89ead8091d72.png)

いわゆるif文です。
条件式は最初の方に定義したテーマの数を取得してる変数（今回の説明だと「投稿数」）が3以下になった時に処理をさせます。
左側に変数（投稿数）、真ん中には「次の値以下」、右には3を入力
![スクリーンショット 2023-03-11 16.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/11aa800e-4953-e81d-36bc-f0182709bf63.png)
今回は「はい」だけ使うので、「いいえ」の時の処理は何もしません。

チャネルに投稿するので、アクションをクリックして、Teamsから「**チャットまたはチャネルでメッセージを投稿する**」を選択します。
![スクリーンショット 2023-03-11 16.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/8d72b5f5-baf3-d8b6-308d-4f6df8572f54.png)

あとは、投稿するチームとチャネルを選んで、適当なメッセージ内容を入れればこれでOKです！
![スクリーンショット 2023-03-11 16.34.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/25e03a02-bdca-fa98-2cb5-adb3365a6ea1.png)