OmniAICreator/Qiita-1.07M huggingface dataset:
暖かい冬のために自宅に薪暖炉を作る方法

国内の冬が他の温帯諸国のように厳しくて寒いわけではない同様に、家の中に暖かい炉を配置することは不可能ではありません。 、ヨーロッパの住宅建築のような印象で豪華なハイライトを作成するのにも役立ちます。 さらに、買い物にお金がかかりやすく、自分のアイデアと創造性に応じて完全に独自の暖炉を作ることすぐに暖かい冬を過ごすために、以下の屋内薪暖炉の手順に従ってください。
家に暖房システムを構築する必要がありますか?
調査によると、日本では室内暖房システムの設計と構築は全く普及していません。 特に南部地域ではほとんど寒さがなく、亜赤道付近の気候で一年中暑いため、ヒーターの使用は絶対に必要ありません。 

家に暖房システムを構築する必要がありますか?

しかし、暖炉は周囲の雰囲気を暖めるために使用されるだけではありません。さらに、風水の視点からの外観は、家の所有者にとって非常に良い運気を変化させ、維持することにも役立ちます。 非常に多くの人が、リビングルーム、寝室、さらには家族のダイニングルームに適した、満足のいく暖炉モデルに「投資」することを意識しませんでした。

さらに、今日では、伝統的な薪や石炭を燃やし暖炉モデルに加えて、使用ニーズに応じて熱レベルを調整することに沿った電気暖炉もあります。デザインを見つけることができます。じっくり、「家に暖房システムを構築する必要がありますか?」という質問には、あなたのニーズと好みに大きく依存します。が快適になります。

薪暖炉を設計する際の注意点
 家に薪暖炉を 作る方法は、電気暖炉を作る方法とは大きく異なります。 なぜなら、電気暖炉の場合は基本的な設置だけで十分ですが、木炭暖炉の場合はそれだけではあり ませ ん。効果的な薪暖炉の設計を開始する前に、次の注意事項にご留意ください。

正しいデザインスタイルを決める
正しいデザインスタイルを決める

暖炉は空間全体の家具の一部とも考えられ、部屋の美的イメージの重要な部分でもあります。最初に念頭に置いて必要があるのは、全体のスタイルに最も適したデザインスタイルを決定することです。 具体的な例としては、部屋がクラシックな家具を備えた伝統ような建築様式である場合、デザインする暖炉もこのスタイルでいられないということです。

建材を選ぶ
建材を選ぶ

この仕事の成否を大きく左右するのは建設資材です。 現在、ほとんどの人が屋内暖炉を建てるために選択する 材料は、木材、セメント、石の３つです。それぞれの素材には独自の特徴がありますがあり、例えば木製の暖炉は家に魅力と優雅さを両立できることができ、セメントで作られた暖炉は非常にユニークに見えるように塗装され装飾されます。強さ、そして何より長期にわたって耐久性を実現します。石で作られた暖炉は、寛大さと自由の常に美しさを持っていますが、少し多くのスペースを必要としますが、他の素材に匹敵しますてやデザイン装飾が簡単です。しかし、石造りの暖炉は、上記の２つのタイプのどちらよりも保温性と断熱性に優れています。

暖炉のサイズを計算する
暖炉のサイズを計算する

これが、多くの人が最も不必要な間違いを犯しやすい原因です。ミニ暖炉の作り方と大きな暖炉の作り方を常に明確に区別しているのは偶然ではないことを常に覚えておいて ください 。重要な要素であるため、大きな暖炉は熱容量が高く、それも同様です。 ただし、屋内スペースの許容範囲が制限されている場合、サイズが大きすぎる薪暖炉を設計することはできません。が短くて息苦しいだけです。

自宅で薪ストーブを作って暖かい冬の過ごし方
とりあえず高価ではないコストで、 安価な木製暖炉を設計することは、確かに多くの人に選ばれるでしょう。 、とりあえず今年の冬が寒かったとしても、もう心配する必要はなく、家族にとって印象的なインテリア空間が得られることは間違いありません。以下は、薪を燃やす屋内暖炉の作り方に関するステップバイステップのガイドです。

自宅で薪ストーブを作って暖かい冬の過ごし方

ステップ1：詳細な暖炉の設計図を作成します。以前に計算されたパラメータに基づいて、同時にそのような暖炉のスタイルを決定します。設計図が詳細であればあるほど、実装する際に便利になることに注意してください。

ステップ 2: 家の中に暖炉を建てるエリアを決定します。ちなみに、家に暖炉を建てるときは注意点があります。暖炉の面積よりも大きな土台を建てて、正面の床面積を増やす必要があります。


ステップ 3: 厚さ 5 ～ 7 cm の基礎の砕石を注いで暖炉の作り、モルタルを注いでしっかりと閉じます。炉の設計と比較して、基礎の厚さをより正確に決定します。


ステップ 4: 基礎が凍結して乾燥するまで待ってから、炉の次の部分の構築を続けます。 耐熱セラミックを使用して、基礎の表面から壁まで炉の内部を覆います。

ステップ 5: 暖炉の詳細図面に沿って暖炉を完了し、その上に暖炉の煙突を設置し、そのさと操作性、空気濾過を確認します。

ステップ6: 上記のステップをすべて完了したら、内側の耐熱セラミックパネルも含めてすべてを確認します。すべてが完了したら、暖炉で使用するための薪を燃やすことができます。

上記は、家の中に薪暖炉を作る方法と、読者に送りたい進行プロセス中の重要な注意事項について共有した情報です
IPv6-onlyのEC2を作成しIPv4から接続する方法

## 背景
* IPv6/IPv4 dualstackまたはIPv6-onlyのWebサイトにIPv6でアクセスできるかを試したい
* ただし、ローカル環境からはIPv4しか利用できない
* IPv6 OnlyのEC2インスタンスを作成したが、IPv4しか利用できないため直接接続できない
* また、IPv6ではSystems Managerエンドポイントにアクセスできない（執筆時点）ため、SSM Session ManagerからEC2インスタンスにアクセスできない

## 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/1f36d1bf-62b4-0872-7db4-7b2eeb3e4152.png)
* IPv4/IPv6をもつEC2インスタンス①を作成する
* EC2インスタンス①のIPv6アドレスを使用して、IPv6のみを持つEC2インスタンス②に接続する
* EC2インスタンス②からEgress-only Internet Gatewayを使用してIPv6でInternetアクセスする

## 実装
### VPC作成
1. IPv6を有効化したVPCを作成する（IPv4アドレスは何でも）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/63be091e-ad46-42d9-f89e-fda6819869e1.png)

### サブネット作成
1. IPv4/IPv6サブネットの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/45d00df5-50c2-7f6e-7710-5d026b973bfb.png)
1. IPv6サブネットを作成する（IPv4 CIDR block設定をNo IPv4 CIDRにする）

### InternetGateway作成
1. InternetGatewayを作成し、VPCに紐づける
1. IPv4/IPv6サブネットのルートテーブルのデフォルトルートをInternetGatewayにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/f2fd20d2-8d42-ef07-c0ef-56e4cac1eb13.png)

### Egress-Only InternetGatewayの作成
1. Egress-Only InternetGatewayを作成し、VPCに紐づける
1. IPv6サブネットのルートテーブルのデフォルトルート（IPv6）をEgress-Only InternetGatewayにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/8a67c27d-af76-f448-f022-8b7169ac9ea9.png)

### EC2インスタンス作成
1. EC2インスタンス①（IPv4/IPv6）作成
     * IPv4/IPv6サブネットを指定
     * パブリックIP自動割り当て有効化（or 無効化でSSM用VPCエンドポイント用意）
     * **IPv6 IP を自動で割り当てる有効化**
     * インバウンド許可なしSecurity Group設定
     * SSM用ロール設定
1. EC2インスタンス②（IPv6のみ）作成
    * IPv6サブネットを指定
    * VPC内からのみのアクセス許可するSecurity Group設定

### 動作確認
1. Session ManagerでEC2インスタンス①に接続
1. Session ManagerでEC2インスタンス①からEC2インスタンス②にSSH
```
### キー作成（ローカルで取得したキーをコピペでEC2上に作成）
$ cat << EOF > xxx.pem
-----BEGIN RSA PRIVATE KEY-----
........................
........................
........................
........................
-----END RSA PRIVATE KEY-----
EOF

### SSH接続
$ ssh -i xxx.pem ec2-user@[EC2インスタンス②のIPv6アドレス]
```
3. EC2インスタンス②からcurlコマンドを実行するとIPv6アドレスで接続できていることを確認可能
```
$ curl -v https://xxxxxx.cloudfront.net/
*   Trying [IPv6アドレス]:443...
* Connected to xxxxxx.cloudfront.net (IPv6アドレス) port 443
```
【13日目】OSS連携してみたい！(10)OSS連携モジュール(C++)を作るにあたっての小ネタ

この記事は筆者オンリーの[Advent Calendar 2023](https://qiita.com/advent-calendar/2023/aichallenge_racing_for_mas)13日目の記事です。  

# 前回までのあらすじ
OSS連携を思考するに当たり、Python、C++によるROSモジュールの組み付け、及び関連モジュールの調査を行っていました。
毎日投稿するにあたって端折ってしまいましたが、
ROS2モジュールの作成、Autowareのmsgの受け渡し等に必要な小ネタをちょっと書いていこうと思います。

# ROSモジュールの組み付け
[ROSのチュートリアル](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html)を参照していただければよいかと思います。
たいていはこれで事足ります。

# CMakeLists.txt
```CMakeLists.txt
find_package(autoware_cmake REQUIRED)
find_package(geometry_msgs REQUIRED)
autoware_package()
```
を追加します。
AutowareのmsgはAutowareの独自メッセージはもちろん、Autoware内にはROS2のメンバーも入っているので。

ament_auto_add_executable()
には、ビルドしたいcppファイル名を追加します
# package.xml
```package.xml
<build_depend>autoware_cmake</build_depend>
<depend>autoware_auto_xxx_msgs</depend>
<depend>geometry_msgs</depend>
<depend>motion_utils</depend>
```
を追加します(xxxはAutowareのモジュール名)。

# cppファイル
```xxx.hpp
#include <autoware_auto_control_msgs/msg/ackermann_control_command.hpp>
#include <autoware_auto_planning_msgs/msg/trajectory.hpp>
#include <autoware_auto_planning_msgs/msg/trajectory_point.hpp>
#include <geometry_msgs/msg/pose.hpp>
#include <geometry_msgs/msg/twist.hpp>
#include <geometry_msgs/msg/pose_with_covariance_stamped.hpp>
#include <nav_msgs/msg/odometry.hpp>
```
# xmlファイル
作成したパッケージ（モジュール）について、追加を行います。
xxxxxxにはパッケージ名、execにはtalker/listenerを追加します。

```autoware_micro_awsim.launch.xml
<node pkg="xxxxxx" exec="talker"/>
<node pkg="xxxxxx" exec="listener"/>
```

のようにAutoware、ROS2に関連するヘッダファイルをインクルードします。
Pleasanterのサイトパッケージで特定のサイトを更新したい

# 前置き
Pleasanterのサイトパッケージをエクスポート→インポートすると、同じ設定のサイトが新規作成されます。このサイトパッケージ、既存サイトを更新することはできないのですが、スクリプトを組んで更新できるようにしてみました。

# 実装概要
以下のようなサイトを用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/ba2a1dcf-37f0-9130-eb7d-63264baca3b1.png)

「サイトパッケージを貼り付ける」欄に、エクスポートしたサイトパッケージのJsonを貼り付け、サイトIDを指定し、プロセスでスクリプトを実行します。

# 実装スクリプト

クライアントスクリプトで実装します。

```javascript

//この関数をプロセスから呼び出します
const updateSite = async () =>{
    $p.clearMessage();
    let ret = {}
    
    //サイトIDを取得
    let siteId = Number($p.getControl('ClassA').val());

    //更新先のサイト設定情報を取得
    await $p.apiGetSite({
        id: siteId,
        done: function (data) {
            ret = data
        },
        fail: function () {
            $p.setMessage('#Message', JSON.stringify({
                Css: 'alert-error',
                Text: 'サイト更新に失敗しました。'
            }));            
        }
    });

    //画面に貼り付けたサイトパッケージjsonを取得
    let ssPackage = JSON.parse($p.getControl('Body').val())
    
    let newData = {}
    newData = ret.Response.Data

    //サイトパッケージ内のSites配列1番目のSiteSettingで更新対象のサイト設定情報を更新
    let ss = ssPackage.Sites[0]
    newData.SiteSettings = ss.SiteSettings
    delete newData.Comments;

    //サイトを更新
    $p.apiUpdateSite({
        id: siteId,
        data: newData,
        done: function () {
            $p.setMessage('#Message', JSON.stringify({
                Css: 'alert-success',
                Text: 'サイトを更新しました。'
            }));
        },
        fail: function () {
            $p.setMessage('#Message', JSON.stringify({
                Css: 'alert-error',
                Text: 'サイト更新に失敗しました。'
            }));
        }
    });

}

```

# 注意点
- サイトパッケージはフォルダからエクスポートすると、配下のサイト全てを取得できますが、記載したプログラムではそのように取得したサイトには対応できていません。特定のサイト単一で取得したサイトパッケージから実施します。
JavaScript / TypeScriptでいざという時、忘れている表現備忘録

ちょっと目を離した隙に、何だったかと忘れてしまうJS関連の表現備忘録

## 型注釈
```
const value : number = 1;

//オブジェクト
const obj : {
	num: number;
	str: string;
} = {
	num : 1,
	str: 'abc'
}

//配列
const numList : number[] = [0,1,2];

```

### プリミティブ型
```
- number
- string
- boolean
- null
- undefined
- any : 型チェックなしでエラースルー
- unknown : どの型でもOKだが、型チェックあり
```

## 型分割
```
const {num, str} = obj
console.log(num);
// 1
console.log(str);
// abc
```

## Object宣言省略
オブジェクト宣言時、変数がプロバティ名と同一の場合は省略可能
```
const num = 1;
const str = 'bcd';

//普通に宣言
const obj = {
	num: num,
	str: str
}

//省略して宣言
const obj = {num, str}

```

## オプショナルチェーン
```
let obj : any = undefined;
console.log(obj.property);
// Error
console.log(obj?.property);
// undefined
```

## スプレッド構文
```
const numList :number[] = [1,2,3];
const extNumList :number[] = [...numList,4,5];

//オブジェクト
const obj = {
	num : 1,
	str : 'abc'
};
const extObj = {
	...obj,
	prop : 'prop',
}
// {num:1 ,str:'abc' ,prop:'prop'}
```

## テンプレートリテラル
```
const str = 'world';
const message = `Hello, ${str}`;
console.log(message);
```

## Null 合体演算子
左辺が null または undefined の場合に右の値を返し、それ以外の場合に左の値を返す
```
const foo = null ?? 'default string';
console.log(foo);
// Expected output: "default string"
```

## 三項演算子
```
const age = 26;
const beverage = age >= 21 ? "ビール" : "ジュース";
console.log(beverage); // "ビール"
```

## 型注釈
```
function func(arg1: number, arg2: string): boolean{
	return true;
}
```

## アロー関数
```
const func = (arg1: number, arg2: string): boolean => {
	return true;
}

//戻り値なし
const func = (arg1: number, arg2: string): void => {
	// do
}
```

## 型定義

```
type NewObj = {
	num: number;
	str: string;
}

//関数型定義
type FuncType = (arg1:number, arg2: staring) => boolean;
const func: FuncType = (arg1,arg2) => {
	return true;
}

//オブジェクト型定義
type NewObj1 = {
	num1: number;
	str1: string;
}
type NewObj2 = {
	num2: number;
	str2: string;
}

//ユニオン型
type unionType = NewObj1 | NewObj2;
const obj1 : unionType = {
	num1: 1,
	str1: 'abc'
}

//インターセクション型
type unionType = NewObj1 & NewObj2;
const obj2 : unionType = {
	num1: 1,
	str1: 'abc',
	num2: 2;
	str2: 'def';
}

```

## ジェネリクス
```
const genFunc = <T>(arg: T) : T => {
	return arg;
}

genFunc<string>('abc');
//以下と同じ意味
const genFunc = (arg: string): string => {
	return arg
}
```

## ユーティリティ型
```

type Person = {
  surname: string;
  middleName?: string;
  givenName: string;
};

//すべてのプロパティをオプションプロパティにする
type PartialPerson = Partial<Person>;

//以下と同じ意味
type PartialPerson = {
  surname?: string;
  middleName?: string;
  givenName?: string;
};

//すべてのプロパティからオプショナルであることを意味する?を取り除く
type RequiredPerson = Required<Person>;

//以下と同じ意味
type RequiredPerson = {
  surname: string;
  middleName: string;
  givenName: string;
};
```
AWSでMFAを有効にしようとした際に「連続する2つのMFAコードを以下に入力」が求められるが何をすればいいかよくわからない問題対策の備忘録

AWSでMFAを有効にしようとした際に「連続する2つのMFAコードを以下に入力」が求められるが何をすればいいかよくわからない問題対策の備忘録

## MFAについて

https://aws.amazon.com/jp/what-is/mfa/

> 多要素認証 (MFA) とは何ですか?
多要素認証 (MFA) は、ユーザーが単なるパスワードよりも多くの情報を入力する必要がある複数ステップのアカウントログインプロセスです。例えば、ユーザーはパスワードとともに、E メールで送信されたコードの入力、秘密の質問への回答、または指紋のスキャンを求められる場合があります。2 つ目の認証形式は、システムパスワードが侵害された場合に、不正なアカウントアクセスを防ぐのに役立ちます。

AWSにログイン後、MFAを有効化する際に表題の手続きが必要になる事がある何を何をすればいいかよくわからない状況になりました..

## 解決方法

以下を参照して解決

https://harionote.net/article/56
> 結局どうすればうまくいったかというと…
> 
> Google Authenticatorに表示されているコードを「MFAコード1」の欄に入力し、30秒程待ってGoogle Authenticatorのコードが更新されたらそれを「MFAコード2」に入力。
> 
> これで「MFAの割り当て」をクリックすることでうまくいきました。

# 参考

https://harionote.net/article/56

https://atmarkit.itmedia.co.jp/ait/articles/2306/28/news040.html

https://aws.amazon.com/jp/what-is/mfa/
RoRでTimeとDateの使い分け

Ruby on Railsでは、TimeとDateは異なる目的で使用される2つの異なるクラスです。以下にその主な違いをまとめます。

# TimeとDateの違い
### Time
`Time`は、日付と時間の両方を扱います。これは、1970年1月1日からの経過秒数として時間を内部的に格納します。`Time`オブジェクトはタイムゾーンを持つことができます。

``` ruby:Timeを使用
time = Time.now
puts time
# => 2023-09-15 12:34:56 +0900
```

### Date
一方、`Date`は日付のみを扱います。時間やタイムゾーンは考慮されません。

```ruby:Dateを使用
date = Date.today
puts date
# => 2023-09-15
```

## 異なる点
- Time
  - 時間やタイムゾーンを扱う必要がある場合、または特定の時間に何かをスケジュールするような場合に使用します。
    - （例：午前9時）

- Date
  - 日付のみを扱う場合、または時間やタイムゾーンを気にする必要がない場合に使用します。
    - （例：誕生日や記念日）

また、Timeクラスは1970年1月1日からの経過秒数として時間を表現するため、1970年より前の日付を扱うことはできません。一方、Dateクラスは任意の年を扱うことができます。したがって、1970年より前の日付を扱う必要がある場合にはDateクラスを使用します。
Pythonで「break文を使った繰り返し処理の強制終了」の動作を確認してみた

# 概要

Pythonで「break文を使った繰り返し処理の強制終了」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/for/index6.html

# 実装

以下のファイルを作成しました。
```sample.py
num = 0
while True:
    print("num = " + str(num))
    num += 1
    if num >= 2:
        break

print("End")

num = 1
while True:
    print("num = " + str(num))
    num *= 2
    if num > 10:
        break

print("While End")
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
num = 0
num = 1
End
num = 1
num = 2
num = 4
num = 8
While End
```

# まとめ

何かの役に立てばと。
バックエンドサービスで環境変数を使ってますか？

はじめまして、よりそうでSREを担当しているうちだです。

みなさんはバックエンドサービスで環境変数は使ってますか？

[The Twelve-Factor App](https://12factor.net/ja/)にも[環境変数を使うんだぜ？](https://12factor.net/ja/config)といったことが書かれています。

そこで、環境変数を使うことで何がいいのかを書いていきたいと思います。
ちなみに、バックエンドサービスはコンテナで実行することを前提としています。

## そもそも環境変数って何？

環境変数というのはOSが提供する変数の一つで、設定した値はプロセスの子、孫と継承されていきます。
主要なOSではほぼサポートされている機構になります。

設定の仕方は使用しているシェルによって異なります。

* bash/zhsの場合

```bash
export foo=var
```

* PowerShellの場合

```powershell
$Env:foo = "var"
```

また、コンテナイメージの場合は実行時にパラメータで環境変数を設定することが可能です。

* Dockerの場合

```bash
docker run --env='foo=var' --env='hoge=fuga' debian:latest env
```

## 環境変数を使うと何がいいの？

では、環境変数を使うことで何がいいんでしょうか？

先程、`コンテナイメージの場合は実行時にパラメータで環境変数を設定することが可能と説明しました。
つまり、コンテナイメージの中に環境依存値を内包しなくて済むんです。

## つまりはどういう事？

例えばDBの接続情報。
本番環境と開発環境では接続するインスタンスはもとより、ユーザー名やパスワードすら違うことはよくあることだと思います。
接続情報を内包してしまうと、本番環境しか使えないコンテナイメージになってしまいますよね？

:::note alert
パスワードはものの例えです。
パスワードのように機密性の高い設定値は環境変数で設定せずにSecretなどを利用しましょう。
:::

## でも開発環境で実行したいものは本番で実行したいモノ(バイナリ)とはちょっと違ったりするよ？

そうですね。
開発環境で動いているものをそのまま本番環境で動かすというのは環境依存値を除外してもわりとレアなケースだと思います。

でも、ステージング環境と本番環境ではどうですか？
ステージング環境で検証が完了したコンテナイメージをそのまま本番環境で実行したくないですか？
もしステージング環境で検証出来たコンテナイメージを本番環境でも実行出来るなら、バイナリの同一性も担保できる上、本番環境とステージング環境で個別のビルドが不要になりますよね。
また、本番で障害が起きたときに本番で実行しているコンテナイメージをローカルで実行するなんてことも出来ますよ。

:::note info
本番で実行しているコンテナイメージをローカルで実行する場合はSecretへのアクセスが問題になることもあります。
機密情報についてはSecretにアクセスできなかった場合は環境変数から取得するような実装をしておくことも有用です。
:::

## 定義ファイルをマウントすればいいんじゃないの？

Dockerなどでローカルでのみ実行する場合はそれでも良いと思います。
しかし、クラウドサービスによっては外部ストレージをマウント出来なかったりします。

:::note info
少し前までのCloud Runなどはストレージのマウントが出来ませんでした。
今でも一工夫必要です(2023/12/8現在)。
:::

## ならコマンドライン引数でいいんじゃない？

コマンドライン引数にした場合、コンテナイメージのENTRYPOINTの指定によってはENTRYPOINT自身を上書きする必要があったり、引数が長すぎてメンテしにくかったり、文字数の上限に達して指定が出来なかったりするのでオススメはしません。

## 環境変数、ちょっと便利かも

CI/CDにも一工夫必要ですが、環境変数を使うことでビルドの無駄を省いたり、トラブルシューティングがしやすくなるので、ぜひ環境変数を使ってみて下さい。
.bubbleという素晴らしいノーコードツール

.bubbleというノーコードツールが非常に素晴らしく思ったので書きました。

まだあまり知られていない？為なのか、検索しても詳しい使い方などの記事は少ないですが、探り探りやっていると意外と使いやすいと思いました。

Pythonでwebアプリを作ろうと思ったのですが、コードの書けない私にはコードの勉強からしなくてはいけなく苦戦している中、.bubbleに出会いました。

私のようにコードが書けないけど何か作ってみたいと思っている方がいれば是非お勧めですので試してみてください。

今後ノーコードツールは普及していくのでしょうか。
Vercel CLI alias のエラーについて (Error: You don't have access to the domain)

# エラーについて
Github ActionsからVercel CLIでVercelにデプロイし、カスタムドメインを割り当てるためにAliasを使った際のエラーになります。

**コマンド**
```sh
url=$(vercel deploy --token=***)
vc alias $url your-domain.com --token=***
```
**エラー**
```
Error: You don't have access to the domain your-domain.com under your-user-name.
```

# 結論
1. カスタムドメインを割り当てたいVercelのプロジェクトにドメインを割り当てた後にエイリアスを実行すること.
2. VercelのTeam内でのプロジェクトの場合、aliasコマンドにscopeオプションをつけること.

```sh
url=$(vercel deploy --prebuilt --token=***)
vc alias $url your-domain.com --token=*** --scope=team-name
```

# 参考文献
https://vercel.com/docs/cli/deploy

https://github.com/orgs/vercel/discussions/1826

https://github.com/vercel/vercel/discussions/4622#discussioncomment-7660776
NCMBのデータエクスポートに使えるGoogle Chrome機能拡張（データストアの全データダウンロード）

[NCMBは2023年3月末をもって終了します](https://mbaas.nifcloud.com/info/2023/11/post-171.html)。

NCMBを利用されている方々は、まずアプリのデータを適切に保全し、移行先を検討する必要があります。NCMBにはエクスポート機能はあるのですが、ダウンロード実行まで時間がかかったり、ファイルストアには対応していないという問題があります。

そこで、本来は管理画面を便利に使ってもらうために作っていたChrome機能拡張に、データ移行に関する機能を追加しました。以下はデータストアの全クラスデータエクスポート機能の紹介です（v1.5より）。

## 動作について

動作は以下のようになります。機能拡張をインストールしていると、データストアのクラス一覧画面でエクスポートメニューが追加されます。このメニューを選択すると、データストアにある全クラスのデータがダウンロードされます。

![1844_console_mbaas_nifcloud_com_-_1213142417.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/c3d2f633-507a-f7d2-9309-90c4e0afb670.jpeg)

## インストール

[Chrome機能拡張のページからインストール](https://chrome.google.com/webstore/detail/ncmb-extension/dglkhlplcpmnbgodhbngcmdfpojkbdnc?hl=ja&authuser=0)してください。

## ファイルについて

ファイルはJSON形式のみになります。このファイルは、別なサービスへの移行に用いる前提としています。

## 制限

この機能拡張は [https://console.mbaas.nifcloud.com](https://console.mbaas.nifcloud.com/) 以下でのみ動作します。また、この機能は管理画面のAPIを使っていますので、APIコール数を消費しません。また、ACLは無視して処理されます。

## コードについて

機能拡張のコードは[NCMBMania/chrome-extension](https://github.com/NCMBMania/chrome-extension)にアップロードしてあります。ライセンスはMIT Licenseです。依存ライブラリとして[URL.js](https://github.com/duzun/URL.js)を使っています（こちらもMIT Licenseです）。

## まとめ

サービスがクローズすると、そのデータにアクセスできなくなります。まずはデータの保全をお願いします。
早期リターンを学ぶ


## 初めに
僕はFlutterを勉強している情報系2回生の学生です。

まだFlutterを勉強し始めて半年ぐらいです！
記事を投稿するのも初めてなので、間違い等ございましたら、ご指摘お願いします🙏🏿

## なぜ学ぶことになったか

インターンの研修でネストが深くなり可読性が落ちているコードを早期リターンを用いて可読性を向上することにしました。そこで今回早期リターンについて学ぶことにしました。

## 早期リターンとは？
「早期リターン」とは、関数やメソッド内で、条件に応じて早い段階で処理を終了させ、戻り値を返すテクニックです。このアプローチでは、条件が満たされない場合、すぐに関数から抜け出すことで、不要な処理の実行を避けることができます。これにより、コードのネストが深くなるのを防ぎ、全体的な可読性を向上させる効果があります。

## 具体例
そんなことを言われても何かわからないですよね笑
下記に具体例を提示します。
***まず早期リターン適用前のコード***

```test.dart
bool isEligibleForDiscount(Order order) {
  if (order != null) {
    if (order.totalAmount > 1000) {
      if (order.customer.isMember) {
        if (!order.isDiscountApplied) {
          return true;
        } else {
          return false;
        }
      } else {
        return false;
      }
    } else {
      return false;
    }
  } else {
    return false;
  }
}
```
こんなコード絶対読みたくないですよね。

***適用後のコード***
```test.dart
bool isEligibleForDiscount(Order order) {
  if (order == null || order.totalAmount <= 1000) {
    return false;
  }

  if (!order.customer.isMember || order.isDiscountApplied) {
    return false;
  }

  return true;
}
```
こんな少なくて済むならそうしますよね。
誰がどうみても早期リターンを適用した方が可読性向上してますよね。

ですが異なる作業を行うメソッドの場合、一つの作業の結果によってすぐに終了してしまうと、他の重要な作業が行われなくなることがあるので、このような場合は慎重に考える必要があります。


## まとめ
この記事を書くことで、早期リターンの利点だけでなく、慎重に扱うべきデメリットにも気づくことができました。全体的に早期リターンは有用ですが、その使用には状況に応じた実装が必要だと感じました！

## 参考記事
https://zenn.dev/media_engine/articles/early_return

https://qiita.com/laineus/items/d618ff90a82891691153
JetsonNanoでいろいろするのに調べた内容をメモ＠202312

起動時にROSのlaunchを実行させたいメモ

前回の調べ時

https://qiita.com/mmt/items/35e034bc8cd0a1a661bc


### 結果的には

.desktopでターミナル呼び出して.bashrcにlaunchしたい内容を記載して実現はできました
ただ、ターミナルするたびにShellが立ち上がるので、やっつけ実装になっちゃったかも

```startup.desktop
Exec=gnome-terminal
```

```.bashrc
/path/to/your/script.sh
```

### 参考URL
* Jetson Nano - その15: Ubuntu起動時にターミナルで自動起動
    * https://fanblogs.jp/nikmaniphonelife/archive/176/0
* Run nodes in tabs of a terminal by roslaunch (e.g. roxterm) edit
    * https://answers.ros.org/question/276821/run-nodes-in-tabs-of-a-terminal-by-roslaunch-eg-roxterm/
TypeScriptのふわっとしている部分を再確認

こんにちは。
ウェブクルー AdventCalendar 11日目の記事です。
昨日は @wc_sangen さんの「 ZIOのスタックセーフの注意点 」でした。

## はじめに
型について理解している気でいてもしっかりと違いを説明できない部分が多々あるなと思い、復習がてら調べ直しまとめていこうと思います。

## それぞれの比較パターン
比較パターンごとに説明していきます。

### 1.any型とunknown型

どちらも型としての定義が完全でないイメージですが具体的な差は以下です。｀
- any型の方がunknown型よりもさらに不明確である
- any型はTypeScriptが型のチェックをしない

言うなればunknown型はTypeScriptが型のチェックをしてくれるため未定義のプロパティやメソッドへのアクセスは不正であるとチェックしてくれます。

```ts
// dataがunknown型の場合

console.log(data) // これはOK

console.log(data.length) // これはNG

console.log(data.pop()) // これはNG
```

### 2.typeとinterface

#### ① typeは継承ができずinterfaceは継承ができる
これはtypeも交差型で対応できまずが、interfaceはデフォルトで備わっているためinterfaceの方が拡張性があるイメージです。

```ts:typeの交差型
type Human = {
    name: string
}

type Taro = Human && {
    glasses: boolean
}
```

```ts:interfaceの継承
interface Human {
    name: string
}

interface Taro extends Human {
    glasses: boolean
}
```

#### ② 同名の型についてinterfaceは自動でマージされる
TypeScript側で良しなにマージしてくれます。

```ts:interfaceの場合

interface Human {
    name: string;
}

interface Human {
    age: number;
}

// 結果
interface Human {
    name: string;
    age: number;
}

```

```ts:typeの場合

type Human = {
    name: string;
}

type Human = {
    age: number;
}

// 結果 エラーとなる

```

```ts:interfaceでも無理な場合

interface Human {
    name: string;
}

interface Human {
    name: number;
}

// 結果 エラーとなる

```

#### ③typeではMapped Typesが使用可能
ここは私自身知らなかったのですが以下です。
typeの場合にはオブジェクトのキーに対してユニオン型の指定ができますが interfaceでは使用できません。

```ts
type JsFramework = "Vue" | "React" | "Angular";
type PossibleFramework = {
  [key in JsFramework]: string;
};
```

interfaceでも無理な場合でもあるように整合性がない上書きではエラーとなります。
結論interfaceの方が拡張性には富んでいますが、チーム開発で使用する場合には注意が必要です。

### 3.Objectの型定義
プロパティが未知の場合の定義としては`Object`,`object`,`{}`があります。
それぞれの違いについて記載していきます。

|                                                 | object | Object | {}  | 
| ----------------------------------------------- | ------ | ------ | --- | 
| 空のオブジェクトを許容する                      | ○     | ○     | ○  | 
| プリミティブ型(null, undefined)の代入を許容する | ×      | ○     | ×  | 

というように一番は具体的なプロパティ単位まで細かく記載がベターですが、それが無理な場合にはobject型で定義するのが良さそうですね。

### 4.ラッパーオブジェクトとプリミティブ型の定義

上と少し関連ある部分ですが、今回はプリミティブ型です。
プリミティブ型には本来フィールドやメソッドはないですが、JavaScript側で良しなにメソッドやフィールドを呼び出せるようにしてくれています。そのことを自動ボックス化と言います。その際にラッパーオブジェクト化してくれています。
これをJavaScript側に任せずに意図的にやろうとすると下記です。
```ts

// プリミティブ型の場合
let count:number = 1;

// ラッパーオブジェクトで定義する

let count:Number = 1;
// or
const initial = 1;
let count = new Number(initial);

```

プリミティブ型とラッパーオブジェクト型の違いは下記です。
- プリミティブ型をラッパーオブジェクト型で定義することは可能だが、逆は不可
- 演算子が使用できない


というように上記からあまりラッパーオブジェクト型で定義する利点はあまりなさそうですね。

## 最後に
今までふわっとしていた部分を再度理解し直すことができました。
やはり解決策を調べるだけでなく、なぜそうなのかと根本から理解し直すことが一番知識に定着しますね。

明日は@tatsuyanamikiの投稿になります。お楽しみに！
ハイパーバイザによるパフォーマンス低下測定

# サマリ
サーバにESXi 7.0をインストールし、その上にAlmaLinux9.1の仮想マシンを構築し、sysbenchを使ってハイパーバイザ仮想化による性能低下を検証しました。CPU・メモリとも性能低下はごく僅かでした。

# 背景
ベアメタルと仮想化のメリット・デメリットとして、CPU/メモリ/ストレージ等へのパフォーマンス影響が挙げられます。一般的に、ハイパーバイザによる仮想化の場合はベアメタル・コンテナ型仮想化と比較して、パフォーマンスが低くなります。

しかし、実際にどの程度低くなるのかを検証した記事は多くありません。以下の記事ではベンチマークを使って評価されていますが使用しているCPUに違いがあります。

https://gihyo.jp/admin/serial/01/baremetal/0002

# 確認方法
sysbenchを使ってCPU・メモリのスコアを評価し、前回の記事のスコアと比較します。ただしベンチマークの実行は各1回です。

https://qiita.com/itortie/items/00bdee02659569e1085b

構築した仮想マシンは以下のスペックです
- cpu/socket : 16
- 2socket 
- MEM 64GiB

メモリも揃えたかったですが、全てのメモリ(256GiB)だとホストサーバのESXiと共有してしまうこと、Swap領域のストレージ容量が確保できずAlmaLinuxが起動できないことがあり、スペックダウンしました。スコアに多少影響があるかもしれません。

# 結果
## CPU
| threads | 仮想化 CPU speed | ベアメタル CPU speed | 仮想化/ベアメタル [%] | 
| --- | --- | --- | --- |
| 1 |  999.11 | 1020.73 | 97.9 |
| 2 | 2020.05 | 2022.73 | 99.9 |
| 4 | 3913.92 | 3949.42 | 99.2 |
| 8 | 7386.69 | 7395.63 | 99.9 |
| 16 | 14363.55 | 14556.50 | 98.7 |
| 32 | 21014.62 | 20776.00 | 101.1 |

## メモリ
| 仮想化 MiB/sec | ベアメタル MiB/sec | 仮想化/ベアメタル [%] | 
| --- | --- | --- |
| 5167.74 | 5258.61 | 98.3 |

## 詳細な結果
### threads=1
```
sysbench cpu --cpu-max-prime=9999 run

CPU speed:
    events per second:   999.11

General statistics:
    total time:                          10.0003s
    total number of events:              9997
```
### threads=2
```
sysbench cpu --cpu-max-prime=9999 --threads=2 run

CPU speed:
    events per second:  2020.05

General statistics:
    total time:                          10.0011s
    total number of events:              20213
```
### threads=4
```
sysbench cpu --cpu-max-prime=9999 --threads=4 run

CPU speed:
    events per second:  3913.92

General statistics:
    total time:                          10.0008s
    total number of events:              39150
```
### threads=8
```
sysbench cpu --cpu-max-prime=9999 --threads=8 run

CPU speed:
    events per second:  7386.69

General statistics:
    total time:                          10.0010s
    total number of events:              73889
```

### threads=16
```
sysbench cpu --cpu-max-prime=9999 --threads=16 run

CPU speed:
    events per second: 14363.55

General statistics:
    total time:                          10.0011s
    total number of events:              143682
```

### threads=32
```
sysbench cpu --cpu-max-prime=9999 --threads=32 run

CPU speed:
    events per second: 21014.62

General statistics:
    total time:                          10.0015s
    total number of events:              210219
```

### メモリ
```
sysbench memory run

Total operations: 52928278 (5291760.94 per second)

51687.77 MiB transferred (5167.74 MiB/sec)


General statistics:
    total time:                          10.0002s
    total number of events:              52928278
```

# 考察
勝手なイメージで、ハイパーバイザ型仮想化はベアメタルと比較して1割程度性能が下がると想像していました。実際に測定してみると、CPU・メモリについてはほぼ差が無いことが確認できました。

ディスクIOについて測定ができていないので、機会があればそちらも試してみたいです。
【UE5】Enum値を文字列化する（自分メモ）

全く覚えられず、毎回毎回 Web検索して探すハメになるので、ここにメモしておく。
```UEnum::GetValueAsString()```を使うとよい。

```C++
const EMyEnum MyEnumValue = GetMyEnumValue();
UE_LOG(LogTemp, Log, TEXT("MyEnumValue = %s"), *UEnum::GetValueAsString(MyEnumValue));
```

関数プロトタイプはこんな(↓)感じ：
```C++
class UEnum
{
    template <typename EnumType>
    static FString GetValueAsString(const EnumType EnumeratorValue);
};
```
initializeメソッドについて

#### Rubyで使用される[initializeメソッド](https://docs.ruby-lang.org/ja/latest/method/Object/i/initialize.html)はどんな役割があるかまとめてみました。

initializeメソッドはクラスがnewメソッドでインスタンス化した時に一度だけ実行されるメソッドです。

引数として必要なデータを渡すことで、インスタンスの中にデータを取り込んだりむことができます。
データを渡さずに、インスタンス化と同時に実行したい処理があるときにもこのメソッドを使います。


##### -記述の方法-
```
class クラス名
  def initialize()
    # ここにインスタンス化と同時に実行したい処理を記述
  end
end
```

#### 実際に記述してみましょう！

今回はCatクラスを作り、2匹の猫を設定しました。
```
class Cat
  def initialize(name)
    puts "実行されました"
    @name = name
  end
  def eat
    puts "美味しそうに#{@name}はご飯を食べました"
  end
end

tama = Cat.new("タマ")
mike = Cat.new("ミケ")

tama.eat
mike.eat
```

##### -実行結果-
```
実行されました
実行されました
美味しそうにタマはご飯を食べました
美味しそうにミケはご飯を食べました
```

##### なぜこの順番で結果が出力されたのでしょう？

最初に`tama = Cat.new("タマ")`が実行されたと同時にinitializeもメソッド内に定義された`puts "実行されました"`が表示されます。

`mike = Cat.new("ミケ")`も同様にインスタンス化されたと同時に`puts "実行されました`"が表示されます。


次に`tama.eat`でCatクラス内で定義したeatメソッドが実行され、`美味しそうにタマはご飯を食べました`が表示されます。

`mike.eat`も同様でeatメソッドが実行され、`美味しそうにミケはご飯を食べました`が表示されます。
＠Outputイベントをモックし、テストする


# はじめに

この記事は[Hubble Advent Calendar 2023](https://qiita.com/advent-calendar/2023/hubble)の7日目[^1]の記事です。
Hubbleのフロントエンドチームではユニットテストに重きを置いていて、ほとんどのテストをユニットテストで書いています。
また、Presentationalコンポーネントでは、Testing Libraryを用いてテストを書いています。
Presentationalコンポーネントから親コンポーネントへの＠Outputイベントをモックするのに少し手間取った経験があるため、方法を書き残します。

# 実際のコード例

```ts:todo.component.ts
import { CommonModule } from '@angular/common';
import {
  ChangeDetectionStrategy,
  Component,
  EventEmitter,
  Input,
  Output,
} from '@angular/core';
import { Todo } from '../../models';

@Component({
  selector: 'app-todo',
  standalone: true,
  imports: [CommonModule],
  template: `
    <ul>
      @for (todo of todos; track todo.id) {
        <li>
          <span>Title: {{ todo.title }} | Completed: {{ todo.completed }}</span>
          |
          <button (click)="toggleStatusEvent.emit(todo.id)">Toggle Status</button>
        </li>
      } @empty {
        <p>No todos found</p>
      }
    </ul>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TodoComponent {
  @Input({ required: true }) todos: Todo[] = [];
  @Output() toggleStatusEvent = new EventEmitter<number>();
}
```

```ts:todo.component.spec.ts
import { render } from '@testing-library/angular';
import userEvent from '@testing-library/user-event';
import { TodoComponent } from './todo.component';
import { Todo } from '../../models';

it('should emit toggleStatusEvent when button is clicked', async () => {
  const todos: Todo[] = [{ id: 1, title: 'Test Todo', completed: false }];
  const { component, user, mockToggleStatusEvent } = await setup({ todos });
  const toggleButton = component.getByRole('button', {
    name: /Toggle Status/i,
  });
  await user.click(toggleButton);

  expect(mockToggleStatusEvent.emit).toHaveBeenCalledWith(1);
});

async function setup(props?: Partial<TodoComponent>) {
  const mockToggleStatusEvent = new EventEmitter<number>();
  jest.spyOn(mockToggleStatusEvent, 'emit');

  const component = await render(TodoComponent, {
    componentProperties: {
      todos: props?.todos ?? [],
      toggleStatusEvent: mockToggleStatusEvent
    },
  });

  return {
    component,
    user: userEvent.setup(),
    mockToggleStatusEvent,
  };
}

```

## 解説

### ポイント1: ＠Outputイベントをモックする

```ts:ts
@Output() toggleStatusEvent = new EventEmitter<number>();
```

```ts:spec.ts
// emit関数をモックする
const mockToggleStatusEvent = new EventEmitter<number>();
jest.spyOn(mockToggleStatusEvent, 'emit');
```

```ts:spec.ts
// componentPropertiesにセットしたモックイベントをreturnする
return {
  // ...
  mockToggleStatusEvent,
};
```

### ポイント2: ボタン要素を取得し、クリックイベントを発火させる

```html:ts
<button (click)="toggleStatusEvent.emit(todo.id)">Toggle Status</button>
```

```ts:spec.ts
  const toggleButton = component.getByRole('button', {
    name: /Toggle Status/i,
  });
  await user.click(toggleButton);
```

# まとめ

このような形で、親コンポーネントへのイベントをモックし、テストすることができました。
明日は [@embokoir](https://qiita.com/embokoir)さんです！

[^1]: 平日のみの投稿なので、投稿日は11日ですが7日目の記事としています。
『IIJ セキュアMX メールボックスプラス』「フィルタリング設定」の癖？（マニュアルには記載が無さそうだった）

## 0. セキュアMX（SMX）の仕様をおさらい

これから記載する内容は、どちらのマニュアルにも掲載が無い様子でした。（2023.12.8現在）

- IIJセキュアMXサービス メールボックスプラスオプション ご利用の手引き［管理者用］
≫ ユーザ単位でフィルタリングを設定する

- IIJセキュアMXサービス メールボックスプラスオプション ご利用の手引き［利用者用］
≫ フィルタリングを設定する

※IIJさんから直接リンク禁止と言われたことがあるのでリンクは貼りませんが。

## 1. 「条件」で「差出人(From)」に「メールアドレス」を記入したところ「含む（完全一致）」ではフィルタに出来なかった。（➡「含む（部分一致）」が無難な様子。）
【IIJサポートからの回答】
> IIJセキュアMXサービスのフィルタリング機能では、差出人としてディスプレイネームを含めたヘッダFromの値を参照しております。
> お知らせいただいたメールを確認したところ、ヘッダFromにディスプレイネームが利用されておりますので、
> お客様が設定している「完全一致」の条件には抵触せずにフィルタリング対象外となっている記録がございました。
> そのため、該当メールを差出人を条件にフィルタリングしたい場合は、
> フィルタリング設定にて、差出人としてディスプレイネームも含む値を指定いただくか、
> 「完全一致」ではなく、「部分一致」で設定いただくことをご検討ください。

## 2. 「動作」で「転送する」にしたが、転送元にもメールが届いてしまう。（➡転送元のメールが転送元ユーザカウントのメールボックスにも保存される仕様だった。）
【IIJサポートからの回答】
> フィルタリング設定で転送した場合、転送元のメールが転送元ユーザカウントのメールボックスにも保存される仕様となりますので、
> {SMXでフィルタリング設定をしているメールアドレス}へメールが届いているのは正常な動作となります。

## 3. 「動作」で「転送する」にしたが、転送元メールアドレスに２通のメールが届いてしまう？（➡同一のSMXメールサーバで複数メールアカウントを持っておりその一方へ転送した場合にしか発生しない仕様？）
※これは次のような構成で試験した場合の動作です。
```
（１）差出人(From)： from@example.com /SMTPサーバ→外部（SMX以外）
（２）SMXでフィルタリング設定したメールアドレス：SMTPサーバ→SMXのサーバ[（２）（３）は同じサーバ]
（３）SMXの（２）のフィルタリング設定で転送先に指定したメールアドレス：SMTPサーバ→SMXのサーバ[（２）（３）は同じサーバ]
```
【IIJサポートからの回答】
> フィルタリング設定の転送機能では、転送される際に、ヘッダToの情報は変更せず、
> エンベロープToを転送先メールアドレスに変更する仕様となります。
> そのため、ご利用のメールソフト(*)側の仕様として
> ヘッダToの情報を参照して表示されるような仕様である場合は、
> 宛先情報として転送元メールにヘッダToとして指定されていたメールアドレスが表示されます。

(*)利用しているメールソフトは、
Microsoft® Outlook® for Microsoft 365 MSO (バージョン 2311 ビルド 16.0.17029.20028) 64 ビット
※「Microsoft 365 Apps for business」の契約です。

:::note warn
なお、この動作の切り分けとして、
転送先に指定したメールアドレスの「MailTAP」（SMXのWebメール）を観察していましたら、
MailTAPまでは、転送先メールアドレスがToとして受信を確認できました。
:::

以上です。
Rubyの@（アットマーク）について知ろう

## @（アットマーク）は何？
Rubyのプログラミング言語では、@（アットマーク）をよく目にします。これはインスタンス変数を宣言するために使用されます。

## インスタンス変数とは？
Rubyでは、クラスを使ってオブジェクトを作成できます。そして、各オブジェクトは異なる状態を持つことができます。インスタンス変数は、オブジェクトごとに異なる値を格納する変数のことです。これにより、オブジェクトが保持するデータを管理することができます。

## インスタンス変数の宣言
@を用いてインスタンス変数を宣言します。例を見てみましょう。

```
class Person
  def initialize(name)
    @name = name
  end

  def greeting
    puts "Hello, #{@name}!"
  end
end
```
ここで、@nameはPersonクラスのインスタンスごとに異なる名前を格納するためのインスタンス変数です。

## インスタンス変数の利用

```
kishida = Person.new("岸田")
kishida.greeting

abe = Person.new("安倍")
abe.greeting

koizumi = Person.new("小泉")
koizumi.greeting

# 出力: 
Hello, 岸田!
Hello, 安倍!
Hello, 小泉!
```

これがRubyでの@の基本的な使い方です。
NCMBのデータエクスポートに使えるGoogle Chrome機能拡張（ファイルストアの全ファイルダウンロード）

[NCMBは2024年3月31日をもって終了します](https://mbaas.nifcloud.com/info/2023/11/post-171.html)。

NCMBを利用されている方々は、まずアプリのデータを適切に保全し、移行先を検討する必要があります。[NCMBにはエクスポート機能はある](https://mbaas.nifcloud.com/doc/current/dashboard/export.html)のですが、ダウンロード実行まで時間がかかったり、ファイルストアには対応していないという問題があります。

そこで、本来は管理画面を便利に使ってもらうために作っていたChrome機能拡張に、データ移行に関する機能を追加しました。以下はファイルストアの全ファイルダウンロード機能の紹介です（v1.5より）。

## 動作について

動作は以下のようになります。機能拡張をインストールしていると、ファイルストアの画面で一括ダウンロードボタンが表示されます。このボタンを押すと、ファイルストアにある全ファイルがダウンロードされ、一緒にファイルストアのJSONデータ `files.json` もダウンロードされます。

![1835_console_mbaas_nifcloud_com_-_1208153533.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ac4a3b0d-0f9e-08cd-7766-78b40ae3ee97.jpeg)


## インストール

[Chrome機能拡張のページからインストール](https://chrome.google.com/webstore/detail/ncmb-extension/dglkhlplcpmnbgodhbngcmdfpojkbdnc?hl=ja&authuser=0)してください。

## ファイルについて

ファイルは、登録されているファイル内容とファイル名でそのままダウンロードされます。また、最後にダウンロードされる `files.json` というファイルはファイルストアのデータに関するものです。このファイルでは、アクセス権限（ACL）情報を保存しています。

移行先はさまざまですが、ファイルストレージがACLに対応している場合に利用できるはずです。

`files.json` は以下のような内容です。

```json
{
	"results": [
		{
			"fileName": "1689665784827.jpeg",
			"mimeType": "image/jpeg",
			"fileSize": 88044,
			"createDate": "2023-07-18T07:36:25.139Z",
			"updateDate": "2023-07-18T07:36:25.139Z",
			"acl": {
				"*": {
					"read": true
				},
				"g37Ca2tI1zMVW6d7": {
					"write": true
				}
			}
		},
		{
			"fileName": "1689665736957.jpeg",
			"mimeType": "image/jpeg",
			"fileSize": 88044,
			"createDate": "2023-07-18T07:35:38.092Z",
			"updateDate": "2023-07-18T07:35:38.092Z",
			"acl": {
				"*": {
					"read": true
				},
				"g37Ca2tI1zMVW6d7": {
					"write": true
				}
			}
		},
        :
	]
}
```

## 制限

この機能拡張は [https://console.mbaas.nifcloud.com](https://console.mbaas.nifcloud.com/) 以下でのみ動作します。また、この機能は管理画面のAPIを使っていますので、APIコール数を消費しません。また、ACLは無視して処理されます。

ファイルダウンロードは、直列処理で行っています（負荷軽減のため）。大量にファイルがある場合には、時間がかかる可能性があるので注意してください。

## コードについて

機能拡張のコードは[NCMBMania/chrome-extension](https://github.com/NCMBMania/chrome-extension)にアップロードしてあります。ライセンスはMIT Licenseです。依存ライブラリとして[URL.js](https://github.com/duzun/URL.js)を使っています（こちらもMIT Licenseです）。

## まとめ

サービスがクローズすると、そのデータにアクセスできなくなります。まずはデータの保全をお願いします。
VitePressのBoilerPlate作ったよ(yarn対応)

こんにちは。あいおんです。

VitePressのBoilerPlateを作ったので公開します。

# つくったもの

 - リポジトリ

https://github.com/aion0721/vitepress-boilerplate

 - デモサイト（GithubPages）

https://aion0721.github.io/vitepress-boilerplate/

 - VitePress公式
 
 https://vitepress.dev/

# 作ろうと思ったきっかけ

某偉大な先輩が社内向けのハンズオンを作るときにVuePressを使われていました。
(そのあとVitePressに移行されていたようですが、めっちゃ前ですね…）
https://qiita.com/ozaki25/items/184e61d2aeaaa1396e26

というわけで、私もそれを継承してハンズオンを作るときにはこれにしようと思ってました。
ただ、VuePressと違ってVitePressではひな形がどうにも作られないようで・・・
(私はyarn派なので、公式ではInitの記載がなかったんですよね)

なので、VitePressで作り始めるひな形を作りました。（Yarnで）
※と思ったんですが、よくよく考えると、別にnpxでinitした後にYarnでやればいいだけだったなと思い始めました。

# 強み（ユースケース）

 - みんな大好きマークダウンでガイドが作れる！
 - Viteなのでめっちゃ早い
 - (比較的)直感的(学習コストが高くない)

# VuePressとの比較

 - Viteなのでめっちゃ早い(二回目)
 - VuePressと比べてPluginが少ない？（Zoomとか使えないのかな・・・）
 - HMRが最高に快適
     - VuePressだと、サイドバーとかの修正はホットリロードでは反映できなかった
     - VitePressは、HMRなのでどこの更新でも反映される

# 感想

yarnでもInitできるみたいでした。。。（作り切ってからReferenceに書いてありました・・・）
https://vitepress.dev/reference/cli#vitepress-init

結局こういうのってBoilerPlate作るのが一番勉強になるんですよね。
（次回から別にBoilerPlateなくてもすぐ作れるまで習熟しちゃうこともありますね）

ちなみに、ロゴはChatGPTくんに書いてもらいました。
ソフトウェアテストの７原則〜品質向上委員会の体験談〜 2レース目

## はじめに
私たちは2023年4月に株式会社ラクスパートナーズのQAエンジニアとして入社して、4人で活動しているチーム【品質向上委員会】です。
4月から3ヶ月間の研修を経て、現在は社内の月報管理システムの開発PJにQAチームとして参画しています。
私たちの活動を、JSTQB認定テスト技術者試験にでてきたテストの7原則に照らし合わせて4投稿のリレー方式で振り返ってみております。

今回は第2レース目！！
前回の投稿をご覧になっていない方は以下のリンクからぜひご覧ください！
[ソフトウェアテストの７原則〜品質向上委員会の体験談〜](https://qiita.com/kinoshitanagisa/items/47be389520e4e037ce11) @kinoshitanagisa 

## 原則３｜早期テストで時間とコストを節約
> 早い段階で欠陥を見つけるために、静的テスト活動と動的テスト活動の両方をソフトウェア開発ライフサイクルのなるべく早い時期に開始すべきである。早期テストは、シフトレフトとも呼ばれる。ソフトウェア開発ライフサイクルの早い時期にテストを行うことにより、コストを低減または削減できる。

### ＜ 経験から考える ＞
新しい開発を始めるとき、開発の初期段階からテストを組み込めないかなとQAメンバーで考えました。まだ、モノができていないのにテストを組み込むとは？と思いましたね。
ここでいう「テスト」とは、実際にモノを動かして行うテストではありません！

では、どういう事かと言うと、、、

### ～ 完成形を想像し、思考のテストを実施 ～
新しい機能の要件定義や仕様の擦り合わせが行われる中で、テストケースを検討するならどうする？と考えるようにしました。このアプローチにより、まだコードが書かれていない段階から潜在的な問題や仕様の改善点を発見し、よりユーザー目線を意識した提案ができたのではないかなと思います。
また、提案するという積極性も養われた気もします。

今後もこの取り組みを意識し、初期段階での働きかけの精度を上げていくことで、後の段階での修正や再作業にかかるコストを削減できると期待しています。

## 原則４|欠陥の偏在
> リリース前のテストで見つかる欠陥や運用時の故障の大部分は、特定の少数モジュールに集中する。テストの労力を集中させるために欠陥の偏在を予測し、テストや運用での実際の観察結果に基づいてリスク分析を行う。（原則 2 で触れたことと同様）

### ＜ 経験から考える ＞
現在の開発PJにおいても各機能の設計や構築難易度の違いから、欠陥の発生数に差が生じています。さらに、画面数やサイトの規模が大きくなれば、多くの機能が付き、影響範囲が広がっていきます。
よって、複数の開発者やチームが作業をすることになり、その開発者・チーム毎にスキルの差も生じ、ある部分では欠陥が多発するなどの「欠陥の偏在」が生じるのかなと感じました。

だからこそ、なにをしたらよいのか、、、

### ～ 欠陥の集中箇所の特定 ～
欠陥が集中している箇所や機能が特定できれば、その部分を優先してテストを実施し、欠陥の数を減らすことができます。また、設計の際に指摘事項として、開発者に意識してもらうことにも繋げられます。

**で！す！が！**

欠陥の集中箇所の特定と簡単に言っていますが、これができていれば苦労はしないです、、、。

今できることとして、まずは過去のテスト実施や不具合報告からバグ分析等を行い、欠陥の集中箇所を特定できるようになることから始めようと計画しています。私たち品質向上委員会の伸びしろは無限大です。

最後まで読んでいただき、ありがとうございました！
次回の「品質向上委員会投稿リレー」は
12/16(土)に@ty04sep さんが、原則5,6についてお話しします
お楽しみに～
Dev Container configuration '.devcontainer/devcontainer.json' file already exists.

# 事象 : Visual Studio CodeでDokcerコンテナを起動しようとしたらエラーで起動できない
- 環境
    - Windows 11 Pro バージョン23H2
    - WSL2
    - Docker version 24.0.6, build ed223bc
    - Docker Desktop 4.25.2
    - Visual Studio Code Version: 1.85.0 (user setup)

Visual Studio Codeで「Ctrl+Shift+P」で「Dev Containers:Open Folder in Container...」を選択してディレクトリ指定で[Open]・・・いつもはコンテナが起動するのにエラーになる

```text:エラーダイアログのメッセージ
Dev Container configuration '.devcontainer/devcontainer.json' file already exists.
```

## 原因 : 不明
VS Codeが何か変にディレクトリを認識していたのかもしれない

### 対応 : Visual Studio Codeでフォルダーを閉じて開く
人に言われるがままにやってみたらコンテナが起動した！

1. [File] > [Close Folder]
1. [File] > [Open Folder] > 対象ディレクトリを選択 > [フォルダーの選択]ボタンで開く
1. 「Ctrl+Shift+P」 > 「Dev Containers:Open Folder in Container...」 > ディレクトリ指定で[Open]
1. 正常にコンテナ起動

#### 間違えた対応
- コンテナもイメージも全部削除してみる : きれいさっぱりコンテナもイメージも削除してやり直してみたが事象は変わらなかった。

```bash
# コンテナ・イメージ(-a)・ボリューム(--volumes)を確認メッセージなし(-f)で削除する
$ docker system prune -a -f --volumes
Deleted Containers:
# ...
Total reclaimed space: 6.1GB

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   1         0         633.1MB   633.1MB (100%)
Build Cache     0         0         0B        0B
```

- 既定のディストリビューションを変更する : 既定のディストリビューションは「Ubuntu」にしてやり直してみたが事象は変わらなかった。

```bash
# 既定のディストリビューションは「Ubuntu」だったような気がしたが違っていた
$ wsl -l -v
  NAME                   STATE           VERSION
* docker-desktop-data    Running         2
  docker-desktop         Running         2
  Ubuntu                 Running         2
# 「Ubuntu」を設定する
$ wsl --set-default Ubuntu
この操作を正しく終了しました。 
$ wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2
```
フォームを作ったら既存のスプレッドシートに自動で紐付けてシート名もいい感じにする方法

# 先日、お手軽にフォームを超産するための記事を書きました。
https://qiita.com/mountaincat/items/7c505462f3f68198c86b

https://qiita.com/mountaincat/items/efe114fe64fb4d73ea37

で、フォームを作ると当然スプシと連携させて集計に使うんですが、これが地味に面倒くさい。
フォーム自動大量生産しても、いちいち一個ずつスプシとの連携を手でやってたら元の木阿弥ですよね。

先日の記事。

てなわけで、フォームをスプレッドシートを自動連係させる。
↓
そのシートをフォームのファイル名にしてあげる。
を、実装しました！

# コードがこちら！

```javascript

//変数formは任意のフォームファイルを取得のこと。
//変数ssは任意のスプレッドシートを取得のこと。

form.setDestination(FormApp.DestinationType.SPREADSHEET,ss.getId());
//フォームの保存先をスプレッドシートに指定
const ftitle = form.getTitle()
SpreadsheetApp.flush();
const sheets = ss.getSheets();
sheets[0].setName(ftitle);
```

これで、スプレッドシートの左端にフォームと連携したシートが自動的に入ります。
フォームの繰り返し自動生産関数と組み合わせると効率化の効果抜群です！
反省：データ可視化でよくやるミスシリーズ①

# やっちゃったよもう。

昨日まで、意気揚々と毎日Viz挙げてましたけど、なんか挙動がおかしいことにちょっと悩んでました。
それは。。。


# いくつか表示されない都市があるけど原因が分かんない。

EDAサボってました・。


データ接続とjoin次第で出たりでなかったりして気持ち悪いなぁ、」なんでだ？と
首をかしげてました。

だけど原因究明には至らず、とりあえず初心者の甘えということでザッカーバーグばりに「とりあえず出す」ことを優先して出してみてました。

# 原因が分かった！

年末年始に肉と魚どっち食べてんの？の派生で、「じゃあ、いつもは何食べてるの＿」を作るために、。都市ごとの売上棒グラフを作ったんですよ、それがこれ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/ce83b136-436d-a761-21c4-00540c1b6b99.png)

え?なにこれ・・・？
津市がめちゃくちゃ金使ってる・・・？

広島も東京都区部超え、ありえなくない？


てなわけで基本い立ち返ってとっとと元データをあたりにいきましたよ、と。
元はe-statのデータをVScode使ってPythonのPandasでぐりぐりやってたので元データから取り直してテーブル化したのがこちら！

どん！

お前か犯人は・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/0b5734b2-75b9-c2f9-5e41-c0da47dced93.png)

いやゴメン、広島市は北海道にあったと思うからそうかも、とも思ったんですが、こりゃ知らんかった・・・。
もうこの場合、都道府県名でやてツールヒントで市区町村名出す方がええんかな。

Tableauでも表示できました・・・。

とはいえ原因は分かったので対策とってViz作り直したのが、こちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5662f0b6-518e-e3b8-684b-9c7404b4ffb8.png)


ああ、可視化が甘かった・・・。
こりゃあ都市で出さずに県平均で出してツールヒントで出した方がええのんか、県当たり一つの市にしたほうがええのか、迷うねー。


元データには市区の名前しか無くて、ちょっとこれをどうするかは緯度経度と紐づけて位置情報に出せるかちょっと勉強してみます~。
Arch Linux 約1年使用レポート

# Arch Linuxとは
ローリングリリースでKISS原則なOSです。
Do It YourselfでWiki提供するからあとはお好きなように、使えないならNewbieなOS使ってねという感じです。
Linuxを全く使ったことがない人が初めに使うOSではないことは確かです。

## 良かったこと
### パッケージマネージャー
本当にパッケージマネージャーは優秀だと思いますバイナリベースのため高速ですし、使い勝手が良いです。
AURが本当に最高です。この機能ために使っていると言っても過言ではありません。

### メモリ使用量
メモリ使用量が少ないです。Ubuntuの場合、GUI起動で800MB、アプリケーション使用で大体7GBは使用しますが、同じ環境(Gnome)でもCUIで130MB、GUIで300MB、アプリケーション使用で1GB〜3GBくらいと、かなり抑えられます。
これはzenカーネルを使用しているのも大きいと思いますが、メモリ使用量を非常に抑えられます。とは言ってもどちらが速いとかはありません。自己満の世界だと思います。

### 最小インストール
当たり前ですが、インストールに不要なものを入れる必要がありません。Ubuntuは最小インストールでもいくつかアプリケーションが付属してきますが、Archは本当に最小インストールが可能で設定アプリケーションすら取り除けます。

## 良くなかったこと
### 不安定
安定はしないです。起きたことは
* suspend復帰時、Xが落ちる
![IMG_8530.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729508/359b236a-09b5-679e-55d0-4db00f8dcab0.jpeg)


* pacmanコンフリクトが急に発生
* systemd-bootで起動、シャットダウンに失敗しまくる(成功の方が多いが、急に失敗したりする)
![IMG_8581.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729508/9e7e5693-2ce9-6314-620e-17b688b079af.jpeg)

* 急にアプリケーションが使用できなくなる
* ターミナルエミュレータが落ちるものもある


と、割と致命的なことが多いです。上記について理由が解明し、適切に対処できれば使いこなすことができでしょう。
Do It YourselfなOSなだけあり、自分で対処しなければ無理です。

### Dockerとの相性
Dockerの相性が良くないように感じます。他のOSで安定動作している環境をdocker-compose upしても落ちたり、コンテナ内であるコマンドを打つとXが落ちたりします。もちろん適切に処置すれば動きますが、解決出来ない人は向いていないと思います。

### デスクトップ環境の不具合
ローリングリリースなので最新のデスクトップが入ります。Gnomeを使用していますが、急に45の状態になりExtensionが全く動かない状態になりました。これはpacmanでパッケージ管理を上手くでき、45の新機能の動向を追うことが出来れば全く問題ないですが、当方そこまで考えず-Syuしていたのが原因です。

加えて最小インストールから構築した場合、Wi-FiがGnome設定画面で弄れないなど、CUIと上手く連携できないことはよくあります。

# 自分が考える向き合い方
OSが大好きでLinuxの勉強がしたい方。ローリングリリース、DIY好きな方。Ubuntuのような固定リリースに疲れた方。シンプルが好きな方はおすすめです。

逆にManjaroやEndeavorもとても勢いがあるため、無理してArchを使う理由は減ってきていると思います。

Distro Watchでも70位くらいですし、Gentooにも負けています。Arch系を使うならEndeavorとか良さそうです。

おま環と言われればその通りです。私には少しまだハードルが高く感じました。

以上です。参考にしてみてください。
収穫逓減とブルックスの法則について

## 予防線

私は経済学についての講義を受けたり、独学で真面目に勉強したりしているわけではなく、耳学問でやっているだけなので、本記事については話半分で聞いてください。

## はじめに

ブルックスの法則は、ブルックスの「人月の神話」で有名なものです。これを当然のものとして受け入れて、アンチパターンだからとにかく人を追加するのをやめよう、という発想になってしまったり、その発想をベースに人と話したりすることは、時として失敗や誤解を生みます。

人や資本を増やせば、**ある程度**は生産量が増大するのが一般であり、そうでないケースであることを示さなければいけません。さもなくば、良かれと思って人が追加されたり、開発は頑固だと思われて見放されたり、ということが起きるかも知れません。

企業は利潤を追求します。その利潤を追求するために、どう開発組織が手伝いができるのか、また、開発組織の手伝いの障害となるのか、これらを話しましょう。

そのために、より視野を広く取り、何が問題なのか、他に類似して考えられることはないか、というのを踏まえて、相手の文脈に沿って説明しなければなりません。

## 一般例; 限界効用の話

人や資本を倍にしても、倍の生産量にはならない、ということの感覚を掴んでもらうために、卑近な例を話します。

あなたは友人たちと一緒に、ボードゲームやTRPGをやろうとしました。

当初、「ELDEN RING TRPG」と「Dominion」とのいずれをやろうかと相談しました。

それぞれの効用(満足度)を比較し、「ELDEN RING TRPG」を選択し、5時間ほどセッションしました。

さて、この時、さらに追加で1時間「ELDEN RING TRPG」のセッションを継続することは、これまでの5時間で得られた効用(満足度)の5分の1以下になるでしょう。むしろ、当初候補から外れた「Dominion」を1時間追加でやるほうが効用が大きいでしょう。

このように、限界効用は逓減していきます。(ここでの「限界」は1単位、という意味で、捉えてください。)

## 収穫逓減

生産関数Fは、人(L)と資本(K)とを引数にとって、生産を出す関数とします。

この時、人(L)と資本(K)をλ倍した時(λは1より大きいとする)、生産量はどうなるでしょうか？　以下のように場合わけがされるでしょう。

1. `F(λL, λK) > λF(L, K)`
2. `F(λL, λK) = λF(L, K)`
3. `F(λL, λK) < λF(L, K)`

それぞれ、次のような名称があります。

- 1は、もとの生産量のλ倍より大きくなるので、収穫逓増。
- 2は、もとの生産量のλ倍と等しいので、収穫一定。
- 3は、もとの生産量のλ倍より小さくなるので、収穫逓減。

営業で考えると、人や資本が少ない状況だと、人を倍にしたり、資金を倍に投入して使えるツールを増やしたりすれば、倍以上の成果が得られる可能性があるでしょう(もちろん戦略や戦術やチームがうまく設定できているという強い前提ありきであるが)。

他方で、人や資本が十分にある状況で、さらに人や資金を追加をしても、結局未開拓の営業先がなくなったり商品の力が弱くなったりして、倍の結果は得られず、収穫は逓減することになるでしょう。

このように、状況によって収穫が逓増したり低減したりもしくは一定だったり、というのは発生するでしょう。

## 収穫逓減の一例としてのブルックスの法則という考え方

状況によって収穫が変わることは、一般にある現象と考えられます。

そこで、ブルックスの法則は、収穫逓減の一例と考えられます。そして、一般の収穫逓減よりもさらに強いことを言っています。つまり、

`F(λL, λK) < F(L, K)`

と、λ倍未満になるのではなく、倍増する前よりも低くなる事象を示していることになります。

単純作業ではないような、チームでの知識労働は、簡単に作業を分解できず、作業を進めるためにはコミュニケーションの量を増やさなければならないこと、これによってブルックスの法則が扱っている強い収穫逓減が起きてしまうのです。

そのため、人や資本を増やして、その上で、収穫を増やすためにはコミュニケーションのオーバーヘッドの増加への対処が求められます。結局は、チームを適切なサイズにしたり、自己組織化したり、チーム間でのコミュニケーションを円滑にしたり、かつ、組織全体をよくする他はないでしょう。

## 補足: 別に学ぶ必要はないが、相手のコンテキストに沿った文章を作る

経済学を学べ、みたいなことは言いません。

新たなことを学んだらそれを応用したくなる気持ちは分かりますし、ブルックスの法則も当然のものとしてそれを話の中で使いたくなるでしょう。

しかし、私達はプロダクトを開発しており、ユーザーやステークホルダーに価値を提供しています。ユーザーの使いやすさを踏まえたUIやUXを考えるのと同じように、ステークホルダーの文脈に合わせて組織や開発のことを話したほうがいいでしょう。

壁があるように感じるのなら、境界線を作るのではなく、こちらか歩み寄り、そして相手にも歩み寄ってもらいましょう。そのために、相手に近づく手法として最も使えるものを使っていきましょう。

なお、私の事例ではありますが、ミクロ経済学の勉強は歩み寄りにはあまり使えないような気がしました。
Ventura で Fink

PDF を、コマンドラインで合体させたいと思い、Fink を導入。

macOS Ventura 13.6.1（22G313）

まずは、以下のものをインストール。

* XCode
* JDK
* X11

ソースのダウンロード:

https://github.com/fink/fink/archive/refs/heads/master.zip

ターミナルから、以下を入力

```
unzip ~/Downloads/fink-master.zip   
cd ~/Downloads/fink-master 
./bootstrap  
. /opt/sw/bin/init.sh 
```
いちどターミナルを閉じ、再度立ち上げる。

```
fink self-update
fink install pdfkittool
```

無事インストールできた。

```
/opt/sw/bin/PDFKitTool load 20231201_004.pdf load 20231201_005.pdf 20231201_006.pdf load 20231201_007.pdf cat output xxx.pdf
```
WordPressで"◯日以内に投稿された記事かどうか"の関数を作るモダンな方法

# 結論
下記コードをコピペして関数名に適当なプレフィックスを追加して使えばいい。

```js
function is_recently_post( int $days = 7, ?WP_Post $post = null): bool {
    /** @var DateTimeImmutable|false */
    $post_time = get_post_datetime( $post );

    if (false === $post_time) {
        return false;
    }
    $days_difference = $post_time->diff(current_datetime());
    return $days_difference->days <= $days;
}
```

# 理由
[公式サイトで"これからの実装にget_the_date('U')やcurrent_time('U')を使うな"と書いてある](https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/)から

[参考](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml)

これで終わりでもいいんですがもう少し説明します。
`get_the_date('U')`や`current_time('U')`で取得できる値は**WordPressタイムスタンプ**と呼ばれるものです。
この値はタイムゾーン対応が環境依存になっており、処理が安定しないことになってしまいました。
そのため、WP5.3以降は**Unixタイムスタンプ同士**での比較にするか、[DateTimeInterface::diff()](https://www.php.net/manual/ja/datetime.diff.php)でタイムゾーンを合わせて比較することを推奨されています[^1]。
上記コードはそれに素直に対応したコードです。

[^1]:ただしDateTimeInterface::diff()は夏時間が絡むと意図しない挙動になり得る可能性が想定されています。
プリザンターのスクリプト開発を少しでも楽にする方法

# はじめに
気づいている人は気づいている事です。プリザンターで開発する際、スクリプトやサーバスクリプトを使用します。  
ブラウザ側で動作するプログラムはスクリプトで登録します。  
しかし、プリザンターでスクリプトを入力する際は単なるテキスト入力でコードエディタとかありません。  
プログラマーとしてはVSCodeとか使用して開発できれば楽になるのですが・・・  
これが可能です。  
一時的な使い方ですが、早く開発したい人にとっては便利なのでご活用ください。
今回はダッシュボードで作成してみます。

# 手順

## 1.ダッシュボードを追加します。
説明不要ですね。
## 2.ダッシュボードの管理＞HTMLに下記を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63349/48d44555-0284-6d00-6447-0f2ccb4c7419.png)
```
<script src="/QiitaSample.js"></script>
```
## 3.ファイルを作成します。
プリザンターインストール場所により変わりますが、Windowsでお勧めインストールでは下記のようになります。  
```
C:\web\pleasanter\Implem.Pleasanter\wwwroot\QiitaSample.js
```
プリザンターではwwwrootがWEBの場合のルートになります。  
注意点はwwwrootはログインしなくてもアクセスできるので、開発環境のみで利用ください。
## 4.スクリプトを記述する。
```
$(document).ready(function(){
    $('#Warnings').after('<div id="Aggregations"><h1>HTMLサンプル</h1></div>');
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63349/a8c59cad-e5d8-7dde-69c8-171561d9279b.png)
## 5.レイアウトの保存を消します。
不要なのでスタイルで非表示にします。
```
button#UpdateDashboardPartLayouts {
  display:none;
}
```

## 6.あとはコードをガシガシ書きましょう。
本番環境にする場合は適当に分割するなりしてください。

# 最後に
これでプリザンターのスクリプト画面に依存する事無くコーディングができます。  
なお、ブラウザの設定によってはキャッシュによりスクリプトが更新されない場合があるので、その場合は、キャッシュを無効化してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63349/20a6ff1a-fab3-5fd7-1cab-98cbb8c8070b.png)