OmniAICreator/Qiita-1.07M huggingface dataset:
【Tex】documentclassで「File 'plistings.sty' not found.」となったときの対処法

# 問題

以下のコードを書いて，{ltjsarticle}という文章クラスを適応しようとした．

```
\documentclass[a4paper,12pt]{ltjsarticle} % 文章クラスとオプション
```

しかし，以下の画像のように，「File 'plistings.sty' not found.」というエラーが発生した．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967944/bb346167-2180-5caa-76f4-34274d649140.png)

# 解決法
## 1.'plistings.sty'のインストール
'plistings.sty'は標準的なパッケージではないため，手動でインストールする必要がある．

以下のリンクで配布されているため，ダウンロードする．

https://github.com/h-kitagawa/plistings

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967944/5f879ac7-f2a6-4b2d-0d92-85ac6be7007e.png)

## 2.ファイルの配置
ダウンロードした'plistings.sty'ファイルを以下のいずれかのディレクトリに配置する．

・プロジェクトフォルダ（.texファイルと同じディレクトリ）


・TeXディストリビューションのローカルディレクトリ（すべてのTexファイルで使えるようになる）
```
 <TeXディストリビューションのパス>/texmf-local/tex/latex/local/  %ローカルディレクトリ
```

## 3.インデックスの更新
TeX LiveやW32TeXなどを使用している場合、インデックスを更新する必要があります。以下のコマンドを実行してください
```
mktexlsr
```

## 4. LaTeXコード内で確認
正常にインストールされた場合、以下のようなコードでエラーが解消されます。
```
\usepackage{plistings}
```

# 参考文献
link : https://github.com/h-kitagawa/plistings
Salesforceのコピーで気をつけること～コピーボタンが標準でない場合～

Salesforceコピーで気をつけることををまとめました


### 取引先のコピーボタンについて

通常のカスタムオブジェクトや標準オブジェクトには
「コピー」ボタンがありますが、
取引先にはデフォルトの「コピー」はありません

ヘルプではコピーボタンを作成して代用することがお勧めされています

なので、もしも取引先のコピーを実装したい場合、
以下のヘルプのようにコピーボタンを作成することをおすすめします

・取引先の [コピー] ボタンを作成する
https://help.salesforce.com/s/articleView?id=000316430&type=1




### 行動のコピーボタンについて

行動のコピーも癖があります。
特定の条件の場合、コピーボタンの表示ができません

メンバー招集機能の行動については、行動に被招集者がある場合の、招集側のレコードに標準機能の [コピー] ボタンが表示されます。しかし、以下の場合は [コピー] ボタンが表示されません。

・被招集者がいない行動
・招集された側の行動

*招集されたユーザのカレンダーから行動を開く場合などがこれにあたります。また、被招集者のない行動や招集された側の行動に、 標準の [コピー] ボタンを表示させる設定はありません。


そのため、以下のヘルプのように招集機能を使用していない場合の行動についてはカスタムボタンを作成して対応することが進められています。

もしも行動でコピー機能を実装したいが標準コピーボタンが表示されない場合、以下のヘルプを見てカスタムボタンを作成することをお勧めします


行動のコピーボタンが表示されない
https://help.salesforce.com/s/articleView?id=000331780&type=1
DNS queryのRDビットの有無

DNSのqueryのRDビットについてどうだったか忘れたので検証構成を作り、キャプチャを実施して確認してみました。
構成は以下です。
![dns_20241227_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679222/7bdd3a79-c707-9245-fa3a-50a3a0315afa.png)

DNSクライアントからdigコマンドでBIND9にて構築したキャッシュDNSサーバにqueryを投げ込み、①と②でキャプチャを実施。

①でのキャプチャ
![dns_20241227_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679222/af5209cc-95b4-e8a0-1fed-d26af5216b20.png)
RDビットが1になっています。

②でのキャプチャ
![dns_20241227_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679222/d7c3b4c0-03b2-b4cd-f990-0018bfa59129.png)
RDビットが0になっています。

DNSクライアント→キャッシュDNSサーバのqueryではRDビットは1
キャッシュDNSサーバ→権威DNSサーバのqueryではRDビットは0
となっていました。
実際にキャプチャして確認するのは面白いかも。
【小ネタ】RDSは7日以上停止できないって知ってました？ ～AWS100本ノック～ 20/100

# はじめに
みなさん、AWS使っている中でコスト削減のために不要な時間は稼働を止めたいってなりますよね？
そろそろ年末年始休みですし、本番環境はさておき、開発環境や検証環境は止めようって周りの人から言われたりする人もいるでしょう:thinking: 

DBでRDS、アプリーションにEC2やECSを使うことが多いと思いますが、これらは従量課金なので起動中はずっとお金がかかってしまいます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/1f7bfc0b-5140-16f6-04c2-ff725ba8a4aa.png)
明日から年末年始休みだから止めよう「ぽちっとな」。
よし、全部止まったな。今年の仕事も終わりだ、みなさん良いお年を～！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/f0ed997e-83ed-da6f-80e9-f73d05861cbd.png)
年末年始休みが明け...AWSコンソールを確認しました。
すると、止めたはずのRDSが起動している...ってなったりしてませんか？


# RDS停止の仕様

RDSを停止しようとすると、以下のように7日後には自動起動しますよ～っていう注意書きが出てきます。
メンテナンスに遅れないようにするためらしいのですが、この仕様は設定などで無効にしたり変更することは出来ないようです。
意外と見逃しそうですし、IaCで作業していたら気づかなさそうですよね...

![スクリーンショット 2024-12-26 205650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/0ad663ee-52f2-27e1-7db2-55261b580e52.png)

# 7日以上停止したい場合

RDSの仕様があるとはいえ、7日以上停止したいことはありますよね！
そんな時は、EventBridgeを使って定期的に停止するようにしましょう

詳しくは[こちら](https://qiita.com/namasa/items/dc3f8f8e6934f5aa6a45)の記事で紹介しているので、良かったら読んで頂ければと思います:bow:
NFT Metadata

[Previous << Non-Fungible Token](https://qiita.com/flowcadence/items/152a2fb0c9acb1a6769c)
[Next >> NFT Storefront](https://qiita.com/flowcadence/items/93a05e653883a93b617a)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#flow-developers

<h1>NFT Metadata Contract</h1>

`ViewResolver`コントラクトと`MetadataViews`コントラクトは、オンチェーンのメタデータをNFTに付けるためのスタンダードを実装しています。このスタンダードは、もともとFLIP-0636で提案されたものです。

これは、`NonFungibleToken`コントラクト インターフェースと同じアドレスにデプロイされています。

Source: [ViewResolver.cdc](https://github.com/onflow/flow-nft/blob/master/contracts/ViewResolver.cdc)
Source: [MetadataViews.cdc](https://github.com/onflow/flow-nft/blob/master/contracts/MetadataViews.cdc)

| Network | Contract Address |
|:-:|:-:|
| Emulator | `0xf8d6e0586b0a20c7` |
| Cadence Testing Framework | `0x0000000000000001` |
| Testnet | `0x631e88ae7f1d7c20` |
| Mainnet | `0x1d7e57aa55817448` |

[Flow NFT Catalog](https://www.flow-nft-catalog.com/)というツールがあり、これを使用することで、dapp開発者はFlowエコシステム全体でNFTコレクションの相互運用性を解放(アンロック)することができます。これにより、NFTコレクションのメタデータの検索性と相互運用性が向上します。

このカタログにNFTコレクションを最適化するには、次の作業が必要です。
1. NFTコントラクトを更新し、[core NFT views](https://developers.flow.com/build/advanced-concepts/metadata-views)の実装で、`ViewResolver`と`MetadataViews`をサポートします。
1. 更新したコントラクトをテストネットとメインネットの両方にデプロイします。
1. その後、https://flow-nft-catalog.com のFlow NFTカタログにNFTを登録します。

*Last updated on **Dec 17, 2024** by **j pimmel***

翻訳元

https://developers.flow.com/build/core-contracts/nft-metadata

***

<b>[Previous << Non-Fungible Token](https://qiita.com/flowcadence/items/152a2fb0c9acb1a6769c)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (NFT Metadata)

<b>[Next >> NFT Storefront](https://qiita.com/flowcadence/items/93a05e653883a93b617a)</b>
Alibaba Cloudのイノベーション戦略とクラウド+AIの将来像 その3

## Alibaba Cloud HPN: 大規模言語モデル学習向けデータセンターネットワーク

Alibaba Cloudのイノベーション戦略とクラウド+AIの将来像について、情報収集しことを複数に分けてブログ化した。その1は[こちら](https://qiita.com/ysic/items/84f04abf22d6d1358b58)。その2は[こちら](https://qiita.com/ysic/items/e092e53759fe7865688f)。

今回は、Alibaba Cloudのイノベーション戦略を調べていく中で、個人的にとても興味深いものを見つけたので最後に紹介させてほしい。

<iframe width="560" height="315" src="https://www.youtube.com/embed/aTTeCwHq5AI?si=A-oOW8lEFLcHRfWx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

[SIGCOMM 2024 - Alibaba Cloud HPN - YouTube](https://www.youtube.com/watch?v=aTTeCwHq5AI)

**HPN(High Performance Network)** は大規模言語モデル(LLM)の学習に特化して設計されたデータセンター向けの新しいネットワークアーキテクチャの1つとして、Alibaba Cloudの研究者たちによって生み出された。大規模なGPUクラスターの標準になることを目指しており、Alibaba Cloud内においては約1年前(注: 記事執筆時点で)から導入され稼働しているという。数万ものGPUの相互接続がサポートされ、何千ものLLMモデルトレーニングジョブに優れたパフォーマンスを発揮する。

一般的なクラウドコンピューティングでのネットワーク帯域使用量は常時20%未満で安定しているが、数万GPUという大規模クラスタで実行するLLM学習によって発生するバーストはEthernet規格(400G)の上限に達する可能性がある。また、学習プロセスは障害に敏感で、いずれかのGPUやホストで障害が発生するとプロセス全体の信頼性に致命的な影響を与えるため、これらを解決する必要がある。

HPNアーキテクチャはLLM学習の特性に基づいて構築され、スケーラビリティとパフォーマンス、信頼性の確保を目的としている。当面の目標としては15,000GPUだが、将来的には100,000GPUのサポートが目標だそう。

パフォーマンス目標のためにレイテンシを最小限に抑え、ECMPハッシュの偏りを大幅に減らすことで高スループットを実現。また、2台の独立したToR(Top-of-Rack)を連携させるノンスタック型デュアルToRを採用し、単一障害点を解消することで実運用での信頼性を確保する。

AIを用いて設計のポイントを抽出した。

- **2層デュアルプレーン構造:** 従来の3層Closアーキテクチャではなく、2層構造を採用し、さらに「デュアルプレーン」という技術を導入することで、ECMP（等コストマルチパス）におけるハッシュ偏りを大幅に削減し、トラフィック分散の不均衡を是正している。これにより、大規模なGPUクラスタ（最大15,000 GPUを1つのPodに接続可能）においても効率的な通信を実現する。
- **レール最適化ネットワーク (Tier 1):** ホスト内のGPU間高速接続（NVLinkなど）を活用し、同一「レール」上のNICを同一のデュアルToRペアに接続することで、ラック内通信を最適化している。これにより、多くの学習ジョブが低遅延で最高性能を享受できる。
- **独立したフロントエンドネットワーク:** 学習トラフィックを扱うバックエンドネットワークとは別に、管理、推論、ストレージなどのトラフィックを分離するための独立したフロントエンドネットワークを構築している。

論文中では運用上の知見や関連研究についても紹介されており、たとえば51.2Tbpsシングルチップスイッチを採用した理由としてマルチチップスイッチは長年の運用実績で3.77倍も重大障害が発生していることや、高スループット化に伴う冷却問題への対処など、さまざまな問題への検討・解決を試行したことに触れられている。

**HPNはすでにAlibaba Cloud内の本番環境で運用されており、ToR由来の単一点障害は一度も起きておらず、HPN上でのLLM学習スループットは従来より14.9%高い性能を示すという。**

興味のある方はぜひ公開されている[PDF](https://ennanzhai.github.io/pub/sigcomm24-hpn.pdf)を見てほしい。

[https://ennanzhai.github.io/](https://ennanzhai.github.io/)
windowsでiverilog その173

# 概要　
windowsでiverilogやってみた。
練習問題、やってみた。

# 練習問題
AtCoderを解け。
N個の整数値を受け取り、一度の操作ですべての数を2で割る。割り切れなくなるまで割っていった時、何回割ることが出来るか？


# サンプルコード

```

module test;
	integer stdin = 'h8000_0000;
	integer n,
		a,
		b,
		c,
		ch,
		v,
		p;
	reg [7:0] pc;
	reg [7:0] str[0:9];
	initial
	begin
		pc <= 10;
		v = 100;
		b = 0;
		p = 0;
	end
	always #1
	begin
		case(pc)
		10:
		begin
			ch = $fscanf(stdin, "%d", n);
			pc <= 20;
		end
		20:
		begin
			ch = $fscanf(stdin, "%d", a);
			pc <= 30;
		end
		30:
		begin
			if (a < 2)
			begin
				pc <= 50;
			end
			else
			begin
				a = a / 2;
				b++;
				pc <= 40;
			end
		end
		40:
		begin
			if (a % 2 == 1)
			begin
				pc <= 50;
			end
			else
			begin
				pc <= 30;
			end
		end
		50:
		begin
			if (b < v)
			begin
				v = b;
			end
			p++;
			if (p < n)
			begin
				b = 0;
				pc <= 20;
			end
			else
			begin
				pc <= 60;
			end
		end
		60:
		begin
			$write("%d", v);
			pc <= 70;
		end
		70:
		begin
			$finish(0);
		end
		endcase
	end
	initial
	begin
	//	$monitor("%d %d %d %d", pc, b, a, v);
	end
endmodule




```

# 実行結果

```
>vvp a.out
3
8 12 40
          2
```

以上。
Javaで「フレームに含まれるペインの取得とコンポーネントの追加」の動作を確認してみた

# 概要

Javaで「フレームに含まれるペインの取得とコンポーネントの追加」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/tutorial/jframe/index6.html

# 実装

以下のファイルを作成しました。

```Sample.java
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Container;
import java.awt.BorderLayout;

class Sample extends JFrame{
  public static void main(String args[]){
    Sample frame = new Sample("MyTitle");
    frame.setVisible(true);
  }

  Sample(String title){
    setTitle(title);
    setBounds(100, 100, 728, 400);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton btn = new JButton("MyButton");

    add(btn, BorderLayout.CENTER);
    Container contentPane = getContentPane();
    contentPane.add(btn, BorderLayout.SOUTH);
  }
}
```

以下のコマンドを実行しました。

```
$ javac Sample.java 
$ java Sample 
```

実行結果は以下のとおりです。

![Screenshot from 2024-12-27 07-00-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/e61b5603-3359-2115-8e72-8485b2b75296.png)

# まとめ

何かの役に立てばと。
c1kその後

10.0Rが出てビルドしてインストールしてずっと動いてます。

https://dmesgd.nycbug.org/index.cgi?do=view&id=7645

```
c1k: {1} uname -a
NetBSD c1k 10.0 NetBSD 10.0 (M83XXX) #0: Mon Apr  8 15:25:11 JST
 2024 hiroki@netbsd2:/usr/home/hiroki/netbsd-src/sys/arch/evbar
m/compile/obj/M83XXX evbarm
c1k: {2} uptime
 6:11AM  up 262 days, 12:39, 2 users, load averages: 0.00, 0.00,
 0.00
```

tmux上でirssiを動かしてefnetの#zrouterに入っています。

あとmp3ファイルを置いてhttpでI2Sを出したモジュールのmpg123に渡しています。

先日予備機が手に入りました。

![20241225165752518 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/e736c416-2bcc-2242-373c-03bf953de2aa.jpeg)

このモジュールはFWのコネクタでシリアルが外に出ているので便利です。

rootfsはパラレルIDE 2.5incのドライブをUSBで使っているのですが、以前はときどきハングしてたのですが、リリースをインストールしてからは落ちてません。

1台目のときにu-bootをキーボードをがしゃがしゃ叩いて無理やり止めたので、ちゃんと調べたいと思います。

基板にmini PCIeのコネクタがあるのでいつか使えるようにしたいな。(2025年の最初の案件で出来ました)
OCIのGenAIで開発してたらDBによってパラメータが違った

## 前置き
現在、OCIのGenerativeAI（以下GenAI）を用いたシステム開発を行っております。
その中でそんなの知らんがなとか思った実績を共有するべく、発信します。

## 経緯
ここまで、OCIで開発を行うのにあたって、データベースをBaseDBで実施しておりました。
しかし、今後、製品化に向かうのにあたり自動でメンテナンスを行ってくれるという点に惹かれて、AutonomousDBで作り直すことにしました。
BaseDBはテクニカルにカスタマイズが可能なDB、AutonomousDBはOracleが管理してくれるオートマチックなDBと捉えていただけると分かりやすいかと思います。
今後、稼働する顧客が増えることを想定すると、オートマチックに管理運用していく必要があると考え、DBの切替を決意しました。

## 起こったこと
さて、そんなこんなで元々OracleAPEX（ローコードツール）で画面は作っていたので、サクッとエクスポートした資産をインストールして画面を実装し、動作させてみたところ、何やらエラーが発生しました。

それがこちら。
Add error onto error stack: ORA-20000: Oracle Textエラー:
DRG-50857: oracle error in dbms_vector_chain.utl_to_chunks
ORA-20003: invalid value for OVERLAP parameter

ん？
chunk_params CLOB := '{"max": "250", "overlap": "10%", "language": "JAPANESE", "normalize": "all"}';
多分、このチャンクのパラメータのことを言っているのですが、マニュアルを追ってみても、他のサイトを見ても記載感が同じで原因不明。


chunk_params CLOB := '{"max": "250", "overlap": "10", "language": "JAPANESE", "normalize": "all"}';
overlapに関するエラー内容の為、試しに上記のようにすると、
ORA-20000: Oracle Textエラー: DRG-50857: oracle error in dbms_vector_chain.utl_to_chunks ORA-30585: テキスト・チャンク化のOVERLAPが無効です - '10'

うーん
パラメータがDBによって異なるなんて書いてないのであえなく、詳しい人に相談。

すると、このoverlap、なんと整数として記載する場合は、左のmaxに対してのパーセンテージ数として書く必要があるらしく、それで直った例があるとのこと。

つまり、
**chunk_params CLOB := '{"max": "250", "overlap": "25", "language": "JAPANESE", "normalize": "all"}';**

こういうことですね。

試しに修正したところ、無事に処理が実行できました。




いや分からんｗｗｗｗ



BaseDBでは、もとのパラメータで出来ていたのも相まって謎すぎますね。


同様に躓いた人がいたら試してみてください！


:::note info
##終わりに
現在、2025年4月の製品化に向けて開発を進めております。
是非、興味がありましたらご連絡ください！
ilasmでstack machine その62

# 概要
ilasmでstack machineやってみた。
練習問題やってみた。

# 練習問題
AtCoderを解け。
N個の整数値を受け取り、一度の操作ですべての数を2で割る。割り切れなくなるまで割っていった時、何回割ることが出来るか？


# サンプルコード

```

.assembly AtCoder {}
.method public static void Main() {
	.entrypoint
	.locals init ([0] int32 min, [1] int32 n, [2] string line, [3] string[] lines, [4] int32 i, [5] int32 a, [6] int32 c, [7] bool, [8] bool, [9] bool, [10] bool)
	ldc.i4.s  100
	stloc.0
	call  string  [System.Console]System.Console::ReadLine()
	call  int32  [System.Runtime]System.Int32::Parse(string)
	stloc.1
	call  string  [System.Console]System.Console::ReadLine()
	stloc.2
	ldloc.2
	ldc.i4.1
	newarr  [System.Runtime]System.String
	dup
	ldc.i4.0
	ldstr  " "
	stelem.ref
	ldc.i4.0
	callvirt  instance  string[]  [System.Runtime]System.String::Split(string[],  valuetype  [System.Runtime]System.StringSplitOptions)
	stloc.3
	ldc.i4.0
	stloc.s  4
	br.s  loop7e
loop30:
	ldloc.3
	ldloc.s  4
	ldelem.ref
	call  int32  [System.Runtime]System.Int32::Parse(string)
	stloc.s  5
	ldc.i4.0
	stloc.s  6
	br.s  loop5e
loop41:
	ldloc.s  5
	ldc.i4.2
	rem
	ldc.i4.1
	ceq
	stloc.s  7
	ldloc.s  7
	brfalse.s  loop51
	br.s  loop69
loop51:
	ldloc.s  6
	ldc.i4.1
	add
	stloc.s  6
	ldloc.s  5
	ldc.i4.1
	shr
	stloc.s  5
	nop
loop5e:
	ldloc.s  5
	ldc.i4.1
	cgt
	stloc.s  8
	ldloc.s  8
	brtrue.s  loop41
loop69:
	ldloc.0
	ldloc.s  6
	cgt
	stloc.s  9
	ldloc.s  9
	brfalse.s  loop77
	ldloc.s  6
	stloc.0
loop77:
	ldloc.s  4
	ldc.i4.1
	add
	stloc.s  4
loop7e:
	ldloc.s  4
	ldloc.1
	clt
	stloc.s  10
	ldloc.s  10
	brtrue.s  loop30
	ldloc.0
	call  void  [System.Console]System.Console::WriteLine(int32)
	ret
}





```

# 実行結果

```
>at1
3
8 12 40
2

```

以上。
Playwright + Docker + GitHubActions で実現するCI/CD環境構築

# PlaywrightをDocker上で動かす

## playwright.config.ts

playwright.config.ts に以下の記述を追加します。

**自動サーバー起動**:

- テストを実行する前にnpm run startコマンドを実行して、アプリケーションサーバーを自動的に起動します
- テストが完了すると、自動的にサーバーを停止します

```jsx
  webServer: {
    command: 'npm run start',
    url: 'http://localhost:4200',
  },
```

## Dockerfile

ルートディレクトリにDockerfileを作成し、以下のように記述します。

```jsx
# playwright image を使用。なお、v1.49.1 部分はローカルで動いているPlaywright のバージョンに合わせる。
FROM mcr.microsoft.com/playwright:v1.49.1-noble

RUN mkdir /app
WORKDIR /app
COPY . /app/

RUN npm install --force
RUN npx playwright install
```

## docker-compose.yml

ルートディレクトリにdocker-compose.yml を作成し、以下のように記述します。

```jsx
version: '3.8'
services:
  playwright-test:
    image: playwright-test
    build:
      context: .
      dockerfile: ./Dockerfile
    command: npx playwright test --project=chromium
    
    # レポートをローカルに抽出してくるための記述
    volumes:
      - ./playwright-report:/app/playwright-report
      - ./test-results:/app/test-results
```

## 起動する

ターミナルで以下のコマンドを行います。

```jsx
docker compose up --build
```

以下のようになるはずです。

![名称未設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633884/17eaf6a2-8b77-9812-d5e4-2c88e9a63b2b.jpeg)

# GitHubActionsと連携する

## .github/workflows/playwright.yml を作成する

.github/workflows/playwright.yml を作成します。以下の通り記述します。

```jsx
name: Playwright Tests
on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Install dependencies
        run: npm ci --force
      - name: Install Playwright Browsers
        run: npx playwright install --with-deps --force
      - name: Run Playwright tests
        run: npx playwright test --project=chromium
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

```

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

部分の記述により、mainブランチ、masterブランチにpush、またはPRした場合、自動でGitHubActionsでPlaywrightテストが行われることになります。
Microsoftについて妙に納得した管理ツール多すぎる問題

Microsoftを批判する意図はないのですが、結果的にそういう内容になっているかもしれません。

考えすぎでしょうか？
こういう動画を見ました。

https://youtube.com/shorts/pXW4kixYZvQ?si=86Gq_l0oEt2gD7sp

> マイクロソフトは内戦状態。社員同士を評価させて昇給を決める人事制度なので足の引っ張り合い行為が横行している。

ソースはすでになくなっているみたいですが、探せば引用記事とか出てきます。これは2013年ぐらいに出た大企業の組織構成を風刺したものらしいです。
今は変わっている、と思いたいです。

ただ、Microsoftのところは妙に納得したというか、今直面している問題の根底にはこういったことがあるのか？と思った次第です。

# Microsoft管理ツール多すぎる問題

自分が今把握しているのは以下です。

- Microsoft 365 Admin Center
    - 365の購入、スタッフへのライセンス割当などでよく使う
- Entra ID
    - 仕事でSharepoint APIを調べているときに何度か触った
- Azure Portal
    - Visual Studio Subscriptionsで触った
    - Entraに移行したと思い込んでいた自分は何だったのか（これになかなか気付けなくて時間がかかった）
- Visual Studio Subscriptions Admin Portal
    - Visual Studioのライセンスの割当管理を行う
- Teams Admin Center
    - Teamsに苦戦しているときに見つけた
    - 前仕事で使ったとき、見かけなかったけど何だったのか

それぞれ役割が違っているのに、Visual Studioの請求はMicrosoft 365からダウンロードする。
カオス状態。

# 混乱が生まれやすいです（泣）

Microsoftのアカウントにはいくつか種類があります。

- Microsoftアカウント
- Microsoft 365アカウント

未だに混乱するのですが、個人アカウントと企業アカウントという括りが存在しています。
ほとんどのオンラインサービスではメールアドレスを一意として、アカウント管理がされていることが多いと思いますが、Microsoftは上記が明確に分かれているので、同じメールアドレス1つで、個人用と企業用それぞれにログインできたり、アカウントを作れたりするという状態。

多分ですけど、あとの方から365を入れた企業とか、自前で取得している人とかいるので、混乱していることがあるのではないかと思います。

# Teamsにログインできない

上記の個人アカウントか企業アカウントかで延々とログインできずに認証の無限ループに入るという問題が発生したりしました。
また、Teams Essensialsを購入してライセンスをつけても、デスクトップアプリでログインできない。
お金払ったのに。。。プランを間違えたか・・・？

# Microsoftさんお願いだから・・・

もうちょっとスッキリさせられませんか・・・？
管理する側も使う側も結構混乱しています。
インゲートのメンバーの魅力を新代表より

この記事は クラウドワークス グループ Advent Calendar 2024 シリーズ4の20日目の記事です。

インゲートで代表をしています高橋直道です。
代表に新しく就任して約1ヶ月、日々のメンバーとの会話やお客様訪問などを通して、第一印象として「働くメンバーがとても魅力的」と感じました。
皆さんにもぜひ知ってもらいたく、私が感じた魅力をご紹介します。
とりわけ今回はエンジニアとしてお客様を支援するメンバーにフォーカスしてお話します。（以降はメンバーと呼びます）
# はじめに
## インゲートと私
インゲート(https://ingate.co.jp/) は“人”と“IT”を支援する会社として2006年に設立された会社で、人材紹介事業とITソリューション事業の２軸を展開しています。先月にクラウドワークスグループ入りをされ、旧経営陣がご退任されるタイミングに伴い、私が代表として今年の11月15日に就任しました。会社としてはグループ入りを契機に、グループシナジーを活かした経営を軸として、より成長をしていこうとしている最中です。
私は同じクラウドワークスのグループ会社であるユウクリ(https://www.y-create.co.jp/) の代表も兼務しています。ユウクリにて昨年の代表就任およびグループ入りを契機に改革を推し進めた結果、業績を大きく伸ばすことができ、グループの中でも注目される勢いのある会社となりました。仕事に誇りと愛情をもち、イキイキと働くメンバーの姿をみると幸せに感じます。
インゲートでもそれを実現したく、事業や組織の成長角度をあげることを通して、メンバーやお客様などのステークホルダーにより価値や機会を提供することが私の想いでありミッションです。
# 魅力なところ
## １．プロフェッショナルである
そう感じたエピソードの1つとして、お取引中のお客さまご担当者にご挨拶に伺ったところ、全ての方から当社よりご支援させていただいているメンバーに高い評価/満足を感じて頂けていることです。とりわけ、技術スキルのみならず、人柄だったりコミュニケーションといった定性的なスキルも評価を頂いているメンバーが多かったことが印象的で、こうした生の声を聞けたことは私にとっても、自社に誇りを感じられる良い機会でした。信頼は、メンバーが継続的なスキル向上や実績を積み重ねることの表れであり、その点においても素晴らしいと感じました。
## ２．率直さがある
クラウドワークスの吉田さんも良くおっしゃるのが、いまの時代、働くうえでは「率直さ」が重要であるということです。それがメンバーに備わっていると感じています。
私がメンバーと接する限りでは、相手に対して傾聴し、意義を感じたり共感するといった姿勢があります。エピソードとしては、先日開催された会社の忘年会にて、メンバーから気になる点を色々な角度から沢山質問してもらい、興味を持っていただいていることに嬉しく思いました。
会社の目標/方針を提示してみんなで同じ意識をもって目指すという営みには、疑問や異論をそのままにせず全員が納得するプロセスが必要と考えており、難しいことではあるのですが、メンバーに率直さあるからこそ上手くいくのではないかと感じています。
## ３．利他的である
そう感じたのは、自社にはナレッジをシェアする社内コミュニティがあるのですが、積極的に投稿やコメントがなされているからです。自らが得たこと感じたことを仲間に共有する文化が自然とあり、そうした姿勢は利他的であるからこそです。組織で成果を生み出す営みにおいては、こうしたチームワーク力が必要であるため、その点においても魅力に感じています。
# おわりに
まだ1か月しか経っていないため、これから色々な景色を見ていく中で、また違った魅力も発見できると思うと、ワクワクしています。
総じて言えることは、インゲートは私にとって誇らしい会社であり、だからこそ、自分の介在によって、メンバーの期待を背負い、より成長をさせていきたいと強く思っています。
今後のインゲートにご期待ください。
「ISO-2022-JP」を使用した文字セットの切り替わりによる XSS

# はじめに

本内容は下記記事内の「Technique 1」による文字セットの違いによる XSS について動作確認をした内容です。

「ISO-2022-JP」や文字セット、エスケープシーケンスについて詳しく知りたい方は記事を見るとわかりやすいかと思います。

https://www.sonarsource.com/blog/encoding-differentials-why-charset-matters/

# XSS の発生条件について

今回確認する XSS の発生条件は下記となっています。

1. Content-Type ヘッダおよび meta タグに charset の指定がない、またはブラウザが解釈できない値を指定
2. レスポンスボディ上の XSS ペイロードの前にエスケープシーケンスを出力可能

# 検証時のソースコード

```php
<?php
header('Content-Type: text/html');

$user_input1 = isset($_GET['param1']) ? $_GET['param1'] : '';
$user_input2 = isset($_GET['param2']) ? $_GET['param2'] : '';

$js_escaped_input = addslashes($user_input2);
?>
<!DOCTYPE html>
<h1>XSS TEST</h1>

<body>
    <script>
        var userInput1 = '<?php echo $user_input1; ?>';
        var userInput2 = '<?php echo $js_escaped_input; ?>';
    </script>
</body>
</html>
```

# ブラウザのバージョン

- Firefox 133.0.3
- Google Chrome 131.0.6778.205
- Microsoft Edge 131.0.2903.112

# Firefox での XSS

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971123/b9d63764-133c-6048-7aba-ffe37e5ac081.png)

# Google Chrome での XSS

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971123/2ae277a3-ea04-0c95-6b77-927a6d9c4fb1.png)

# Microsoft Edge での XSS

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971123/673d6b74-9417-f526-87c9-ce0df5df31af.png)

# ペイロードの違いについて

Firefox と Chromium ベースのブラウザでは使用しているペイロードが微妙に異なります。

- Firefox

`/xss/content-type.php?param1=%1b(J&param2=%27;alert(1);//`

- Google Chrome など

`/xss/content-type.php?param1=%1b$B%1b(J&param2=%27;alert(1);//`

クエリパラメータ"param1"で Chromium ベースのブラウザでは本来変更したい文字セット用のエスケープシーケンス「%1b(J」の前に他の文字セット用のエスケープシーケンス(ここではデフォルトがASCIIのためASCIIも除外)を指定する必要があります（なぜ他の文字セットを一度経由しないといけないか理由は不明）。

# まとめ

各ブラウザで charset の指定がない場合に勝手に文字コードが解釈され、スクリプトが発火していることが確認できました。

Chromium ベースのブラウザではエスケープシーケンスの文字化けの違いしか見かけ上の違いはありませんが、Firefox では文字セットの切り替わりを開発者ツール上で確認できるので（バックスラッシュ→円マーク、チルダ→オーバーライン）、色々試してみると面白そうです。エスケープシーケンス自体も表示されなくなります。
extractFaceな処理

メッシュから特定のポリゴン部分を切り出したい。

標準のツールでやるなら
ExtractFaces とか DuplicateFacesなんですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/bec7f9a3-f896-b26e-b34c-71140c346343.png)

こうなっちゃうんですよね。
faceを抽出することで、新しい2つのメッシュに分離されます。

これがちょっとヤダなー

オリジナルのメッシュは維持しつつ、指定したface部分だけ別オブジェクトとして複製したいなぁと。


手っ取り早くやるのであれば

- メッシュを複製
- ExtractFaces　で対象部分を複製メッシュから抽出
- 不要な方を削除

こんな感じでしょうか。



挙動を調べる
--

ExtractFaces　というコマンドが無いので、挙動を調べてみます。
スクリプトエディタを眺めると、2つほどコマンドがみえました。

https://help.autodesk.com/cloudhelp/2022/JPN/Maya-Tech-Docs/CommandsPython/polyChipOff.html

https://help.autodesk.com/cloudhelp/2022/JPN/Maya-Tech-Docs/CommandsPython/polySeparate.html


**polyChipOff**
これで、指定したfaceを複製 または　切り離し（ただし1オブジェクト内）

**polySeparate**
こっちで別オブジェクトに分離する

という流れですね。

ちょっと試してみます。

```
cmds.polyChipOff( 'pSphere1.f[236:237]', dup=True)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/de388023-0bc1-acc7-f5b9-6960a1227ab6.png)

faceが増えてますね

```
cmds.polySeparate( 'pSphere1' )
# Result: ['polySurface1', 'polySurface2', 'polySeparate1'] # 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/d066feac-e907-f36b-7e59-d2b3292ab203.png)

別オブジェクト化されましたねー

うーん。返り値があまりよろしくない。
生成されたメッシュ名が返ってきますが、どっちが目的のメッシュなのかわかりませんね。

方法を変える
--

方法を変えてみます。

- メッシュを複製
- 抽出対象のface以外のfaceをすべて削除

力技ですが、その分シンプルですね。

対象以外のfaceを全て削除する為に、faceIDを全取得する必要があります。
これはapiを眺めていたらあったので

**OpenMaya.MFnMesh.numPolygons()**
を使ってみようと思います。

https://help.autodesk.com/view/MAYAUL/2022/JPN/?guid=Maya_SDK_py_ref_class_open_maya_1_1_m_fn_mesh_html


```python

import maya.cmds as cmds
import maya.api.OpenMaya as om

def getDagNode(target):    
    try:
        sellist = om.MGlobal.getSelectionListByName(target)
        return sellist.getDagPath(0)
    except:
        return None
    
def getShapeFn(dagPath):
    FnShape = None

    if dagPath.hasFn(om.MFn.kMesh):
        FnShape = om.MFnMesh(dagPath)        

    elif dagPath.hasFn(om.MFn.kNurbsSurface):
        FnShape = om.MFnNurbsSurface(dagPath)

    elif dagPath.hasFn(om.MFn.kNurbsCurve):
        FnShape = om.MFnNurbsCurve(dagPath)

    return FnShape

def extractFace(targetFaces,targetMesh):
      
    dupTarget = cmds.duplicate(targetMesh, name = targetMesh + "_extracted")[0]

    dagPath = getDagNode(dupTarget)
    FnShape = getShapeFn(dagPath)
    polyNum = FnShape.numPolygons

    deleteFace = []
    for i in range(0,polyNum):
        if i not in targetFaces:
            deleteFace.append(dupTarget + ".f["+str(i)+"]")
            
    cmds.delete(deleteFace)
```

さて先ほどと同様のポリゴンを抽出してみます。

```
extractFace([236,237],"pSphere1")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/df59f146-8851-9ce6-e796-aa3f78fcae2d.png)

理想的な結果になりました。

改修案
--

このままでは使いづらいので、

- 抽出後の名前を指定できるように
- 選択しているfaceから処理できるように

この辺ができれば実作業で使えるような気がします。
Dataformの個人的な便利ポイント

[BigQuery Advent Calendar 2024](https://qiita.com/advent-calendar/2024/bigquery) の16日目の記事です。が、なんやかんやあって25日のPM15：13に書き始めています。
我ながらスケジュールの見通しの甘さが酷いですね。

皆さまは順調な仕事納めを迎え、穏やかな年末年始を過ごせていることを願っております。
あと風邪や体調不良にもお気をつけください。本当に周囲でびっくりするくらい流行っています。我が家も現在進行系で感染拡大中です。

## この記事について

私は以前、Dataformを使ったデータ基盤の構築にデータエンニジアとして携わっていました。
そして現在はdbt coreを使ったデータ基盤を中心にデータマネージャーを担当しています。

dbtといえばデータ基盤におけるT処理のデファクトスタンダード的な感じになっており、その手軽さや機能の豊富さ、便利さは誰もが認めるところでしょう。
しかし、以前にDataformを触っていた経験からDataformの良さを再認識することもままあります。

この記事では、私が個人的にDataform良いな～と思う点をツラツラと書いていきたいと思います。

#### 注意
dbt coreにはデータマネージャーとして関わっている関係で直接触る機会が多くないため、私が知らないだけでdbtでも簡単に実現できるものもあるかもです。
またdbt Cloudは全く触れたことがありません。使ってる方、正直なとこどうですか？

Dataformについては今年の2024/8頃まで触れていました。以降はリリースノートを追っているのみです。（データ基盤がGoogleCloudで完結しているならDataformで良くない？という思想も持ってます。）

もし「dbtでも簡単にその機能使えるよ！」ってものがあれば、じゃんじゃん指摘いただけますと大変ありがたいです。

## 良いな～と思う点

### ①開発中のSQLXのコンパイル結果が即座に確認できる。
もしかするとこの機能は賛否両論あるかもです。
というのもこの機能では改行1つ、スペース1つでも入れた瞬間に、隙あらばコンパイルしてその結果を表示してきます。そのため場合によっては分かりきったことをエラーとして見せつけられるからです。
私はいかに途中のコンパイルをさせずにSQLXを完成させられるかを密かに1人でチャレンジしながら仕事してました。

/* 暇を見て実際のイメージ追加する。 */

### ②開発中のSQLXの推定バイト数がリアルタイムで確認できる。
BigQueryのクエリエディタ上ではクエリの推定バイト数がリアルタイムで表示されますが、それと同じようにDataformでも確認できます。具体的には開発しているSQLXについての推定バイト数がコンパイル結果に基づいて表示されます。
これBigQueryに慣れていると結構便利だな～と思います。

/* 暇を見て実際のイメージ追加する。 */

### ③開発中のSQLXに基づくリネージ情報がリアルタイムで確認できる。
こちらも推定バイト数と同じように、SQLXのコンパイル結果に基づくリネージ情報がリアルタイムで確認可能というものです。
ただ、急な調査などでDataformのコードを確認する際に、ついついDataform側のリネージを見てしまい実際のリネージとの乖離に混乱することが特にDataform触り始めの慣れていない人でありがちでした。この点はご注意ください。

/* 暇を見て実際のイメージ追加する。 */

### ④独自のGit機能にてコードのバージョン管理ができる。
DataformはGit機能も標準で有しています。Dataformのリリース当初はありませんでしたがCommit前後のコード差分比較（これ未だにリリースノート出てないですよね？）などの機能も徐々に対応されています。もちろんGitHubやGitLabとの接続も可能です。
ちなみにDataformは暗黙のリリースが他よりも体感多い気がしており、リリースノートだけでは拾えない改善点も多いんだろうな～と今でも思ってます。

/* 暇を見て実際のイメージ追加する。 */

### ⑤独自のワークフロー機能にてSQLXの実行管理ができる。
Dataformでは任意のSQLXでワークフローを構成し、管理/実行がGUIで出来ます。実行方法も手動実行やDataform内のスケジューラーの他、API経由での実行なんかも可能です。
またDataformには独自の実行タグが付与可能になっており、SQLXごとに[CS][Mart][管理会計]など好きな管理粒度でタグを付けておくことで、ワークフローの実行対象をタグで指定することも可能だったりします。

/* 暇を見て実際のイメージ追加する。 */

### ⑥これらの機能は全て無料、インフラもフルマネージド。
上に挙げた機能を始め、結構なんでも出来るDataformですが、なんと全て無料で使えちゃいます。「データパイプラインのフルマネージド サーバーレス オーケストレーション」と謳っている通り実行インフラの管理も不要です。少人数になりがち、場合によっては1人データチームも珍しくない状況でインフラの管理って地味に面倒で避けたいですよね。

## さいごに
個人的に好きなDataformについて、運用するなかで多くの人がすぐに便利だな～と感じそうな機能を紹介してみました。

まだまだ他にも出来ることはありますし、地道に機能追加もされています。会社によっては[DataformCore](https://github.com/dataform-co/dataform) を魔改造して独自機能てんこもりで運用していたりもするそうです。

BigQueryをお使いの方、特にデータ基盤がGoogleCloudで完結している企業の方は1度試してみてはいかがでしょうか？

データに関わる全ての人の安寧と幸福を願っております。あとDataform界隈がもっと盛り上がってほしいな～。
clコマンドDLL クラスをDLL化

```
> cl func.cpp /LD
```
```func.h
#include <stdio.h>

#define EXPORT

#ifdef EXPORT
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif

class DLL KONEKO
{
	public:
		int age;
		char name[32];
		KONEKO();
		~KONEKO();
		int func(int a);
};
```

```func.cpp
#include "func.h"

KONEKO::KONEKO()
{
}

KONEKO::~KONEKO()
{
}

int KONEKO::func(int a)
{
	return a + 100;
}

```

```
> cl main.cpp func.lib
```

```main.cpp
#include <stdio.h>
#include "func.h"

int main(void)
{
	KONEKO *kone = new KONEKO();

	int a = kone->func(10);

	printf("%d\n", a);

	return 0;
}

```
LangChainのRunnable対応でハマった話

# はじめに

はじめまして。私は日本工学院八王子専門学校という所で開発をやっています。
現在、AIとの会話アプリをLangChainを用いて開発を行っているのですが、その過程でLangChainのアップデートに対応しようとしてかなり苦労した話を書いていきたいと思います。
## RunnableWithMessageHistory
0.2.7で非推奨となったConversationChainに代わる、チャット履歴管理のための仕組みですね。
私が解説するより、以下の記事を読んだ方がいいと思います。

https://note.com/makokon/n/n850579c34f7d

要するに、前と書き方が変わってしまいました。
また、せっかくなのでと同じタイミングでasyncの導入も進めたのが、地獄の始まりでした。。。
## DBとの連携がうまくいかない
早めにぶちあたったのがこれです。
もともと既存のDB(SQLite)との連携のために、langchain-communityのSQLChatMessageHistoryクラスを継承したCustomSQLChatMessageHistoryを定義して使っていたのですが、こいつをRunnableWithMessageHistoryに渡すと以下のエラーが頻発するようになりました。

> TypeError: 'coroutine' object is not callable


翻訳の通り、コルーチンを関数のように呼び出してはいけないよというエラーになります。
(コルーチンとは: https://zenn.dev/fitness_densuke/articles/understanding_coroutine_in_python)
これがなぜ発生したかというと、CustomSQLChatMessageHistoryクラス内でオーバーライドするasync関数の上に、@propertyデコレータを付けていたからです。
具体的には以下のような感じです

    @property
	async def aget_messages(self) -> List[BaseMessage]:
オーバーライドする関数は元々プロパティだったのですが、非同期化に伴い別の関数に変更していました。その際に、消し忘れていたのが原因でした。

## データベースに会話履歴が書き込まれない
これも最初わけがわかりませんでした。
というのも、

> Error in AsyncRootListenersTracer.on_chain_end callback: AttributeError("'dict' object has no attribute 'type'")

というような極めて曖昧なエラーメッセージしか出てこないため、調査に時間がかかったためです。（さりげなさ過ぎて最初スルーしていました）
厄介なのが、このエラーが出ても例外が発生しないため、会話履歴がなぜ保存されないかを探ろうと思ってデバッガを起動しても原因がわかりませんでした。
エラーメッセージをググり、以下の記事を見つけたことで、ようやくパーサが悪さをしていることに気が付きました。

https://note.com/makokon/n/n2a5dcf7fce11

> 1.  パースロジックを含む完全なチェーンを定義するのではなく、まずメッセージチェーンを定義する。 
> 2.  その後にパースロジックを追加する。

私のコードでは以下のようになっていましたので、

    chain  =  chat_prompt  |  client.ai_client | extract_json
	result  =  await  chain_with_history.ainvoke(
		{"input": input.text}, {"configurable": {"session_id": current_user.id}}
	)

以下のように、出力をjsonとしてパースするextract_jsonをchainの外に出すことで解決しました。

    chain  =  chat_prompt  |  client.ai_client 
	result  =  await  chain_with_history.ainvoke(
		{"input": input.text}, {"configurable": {"session_id": current_user.id}}
	) | extract_json

## 反省	
割と基礎的な知識が欠けていたのと、エラーメッセージでググれば解決する話だったなという印象です。
調査に時間を取られすぎてしまい、必要な機能の実装に時間がかかるのは避けたいところです。
デコレータとか、なんとなく飾り程度に思っていました。（アホ）
【Python】Numpy配列の+=演算に意外な落とし穴（初心者向け）

# a += bの挙動がa = a + bと違うの？！

ことの経緯を説明すると...

最近，E資格を取ろうとして，某有名のディープラーニングの本を迷わず購入！
毎日夜中まで思わず読んでしまっていて...

今日もお昼に買った明治牛乳をちびちび飲みながら，本を参照しながら自動微分を実装していて，自動微分の構想面白い！って思いながら，下記の動作確認コードを実行した．

```python:自動微分を動作確認しようぜ
x0 = Variable(np.array(1.0)) # Nodeを作る
x1 = Variable(np.array(1.0)) # Nodeを作る
t = add(x0, x1) # Add計算して新しいNodeを作る
y = add(x0, t) # Add計算して新しいNodeを作る
y.backward() # 自動微分

print(x0.grad, x1.grad) # 微分を出力
```
図で示すとこんな感じ
![x0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971586/6904a3e0-9ce5-6807-6b4f-3b539beadb43.png)

偏微分を求めてみると，
```math
y = t + x_0 = 2x_0 + x_1
```
なので
```math
 \frac{\partial y}{\partial x_0} = 2, \frac{\partial y}{\partial x_1} = 1
```
ですね．ふむふむ，余裕っすね．さあ，結果見てみよう．

```python:output
2.0 2.0 # 期待値：2.0 1.0
```

なんで？！本通りに実装したはずなのに，なぜ結果が違う？
そもそも，x1の偏微分の2.0ってどう計算すれば出てくるんだい？

gradを計算する処理を見てみると（関係ないところを省略）
```python:core.py
class Variable:
    ...
    def backward(self):
        ...
        for f in funcs:
            ...
            for x, gx in zip(f.inputs, gxs):
                if x.grad is None:
                    x.grad = gx
                else:
                    x.grad += gx # 実はこれはダメだったとは，当時の自分は知らなかった．
```

泣きながらclaudeくんに問い合わせして，かつ色々デバッグしてみて理由がわかった．

# Numpyが頑張って高速化を実現したからこその問題だった
まず，なぜ間違った結果が出たのかでいうと，以下のコードでx.gradが更新されるタイミングと同時に，gxの値も更新されてしまっていた．
```python
x.grad += gx
```
理由辿り着くと以下の感じになる．

1\. x.gradの初期値はgxを参照しているので，同じアドレスを持っている．
```python
if x.grad is None:
    x.grad = gx # -> x.grad address: 4336285360; gx address: 4336285360
```
2\.x.grad += gxの時実は以下のメソッドを使っている．
```python
x.grad.__iadd__(gx)
```
__iadd__メソッドによって，現在のインスタンスを **そのまま更新** する．
x.gradとgxが同じアドレスを指しているので，x.gradの値の更新→ gxが指しているアドレスの値が更新→gxも更新してしまったように見える．
（C++のポインターを学んだ方は既にわかったと思います）

一方，下記の書き方だとセーフ．
```python
x.grad = x.grad + gx
```
なぜかっていうと，x.grad + gxは新しいインスタンスを作って，x.gradが新しいインスタンスを指すように更新っていう手順を踏んで計算することになるので，上記の事象が発生しなくて済む．

```python:修正後
print(f"Before: x.grad id={id(x.grad)}, gx id={id(gx)}")
# x.grad += gxは使ってはいけない．
# numpy配列の+=演算時gxはx.gradと同じアドレスを持つ（モリ効率と計算速度の最適化のためin-placeを使っている故）
# x.gradを更新すると同時にgxも更新されてしまう事象が起きる
x.grad = x.grad + gx
print(f"After: x.grad id={id(x.grad)}, gx id={id(gx)}")
```

```python:output
Before: x.grad id=4403108272, gx id=4403108272
After: x.grad id=4376983216, gx id=4403108272
grads: 2.0 1.0 # 正解！
```

numpyはよく使っているけど，まだまだ理解が足りないなぁって実感した．
それでは！
gem "tzinfo-data", platforms: %i[ windows jruby ]

## 概要
ユーザー登録機能の実装時 Gemfileにdeviseを追加しようとしたところ、エラーの発生。
解決までの手順をこちらに記載。
platforms: %i[ windows jruby ] の指定は、WindowsやJRuby環境でのみこのgemをインストールすることを意味するようです。


## 環境
```
OS：Mac M2チップ搭載
ruby： ruby 3.3.3
Rails： 7.1.3
Bundler 2.3.15
```

## 実施したこと
1.下記記事を参考にコマンドを実施後、bundle install。解決されず。
https://qiita.com/tatama/items/3f0f5e42cb5f75b53817
```rb
bundle config --local disable_platform_warnings true 
```

2.Gemfileの問題の記述部分を修正後、bundle install。
```rb
 gem "tzinfo-data", platforms: %i[ windows jruby ] 
 gem "tzinfo-data" #Gemfileの記載を上記からこちらに変更
```

・下記部分でエラー発生。
```rb
 gem "debug", platforms: %i[ mri windows ]
 
#エラー文
[!] There was an error parsing `Gemfile`: `windows` is not a valid platform. The available options are:
```

・dockerコンテナ内で、下記コマンドを実施。
```rb
 docker-compose run web bundle install
```

・dockerコンテナ内に移動し、deviseのインストール
```rb
 rails generate devise:install
```
AWS AppRunnerを使ってAWS ECRに配置したDockerイメージをAWSにデプロイする

## 記事の概要
簡単なアプリケーションであれば、コンテナイメージまたはソースコードを用意しておくと、AppRunnerを使うことで簡単にAWS上で実行環境を用意してデプロイすることができます。今回は、ECRリポジトリに配置したイメージから簡単なWebアプリケーションをデプロイしてみます。  

Dockerイメージを作成し、ECRリポジトリにpushするまでの手順は以下の記事で紹介しています。  
 [AWS CloudShellでDockerイメージを作成してAmazonECRプライべートリポジトリにpushしてみる](https://qiita.com/e52yamada/items/4ec8080b9b4ab723ebfd)
 
## AppRunnerとは
アプリケーションが簡単にデプロイできる、だと何をしているサービスか分かりにくいですが、AppRunnerは **「Webアプリケーションをインターネット上に公開するために必要なコンテナ実行環境を自動で用意してくれる」** サービスと言えます。  

個人的にAWSのソリューションアーキテクトの方が公開されている以下の資料が分かりやすかったです。  

![image (11) .PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/57071dbb-5242-51cc-4e2d-c1cef6c863bb.png)

出典：https://speakerdeck.com/track3jyo/key-points-of-using-apprunner?slide=18

今回はECRリポジトリに配置したコンテナイメージをデプロイしますが、GitHubなどで管理するソースコードからデプロイすることも可能です。
## AppRunnerサービスの作成
AppRunnerには「サービス」という概念があります。これがアプリケーション実行環境の単位になります。
このサービスを作成していきます。
- AppRunnerの画面で「App Runner サービスを作成」をクリック  

- リポジトリタイプは「コンテナレジストリ」、プロバイダーは「Amazon ECR」を選択し、その他はデフォルトにします。※ 画像だとECR アクセスロールが「既存のサービスロールを使用」になっていますが、「新しいサービスロールの作成」にしてください
![image (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/286d28a8-cb56-4646-4e89-348e760c0949.png)

    - コンテナイメージの URIは「参照」ボタンをクリックすると、作成済みのリポジトリとpush済のイメージのタグが選択できます
    ![image (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/8929cd5c-a09b-956d-e2f3-007ecfd947d7.png)  
    

　　
- サービス名は任意の名前を入力します。**「ポート」は実行するアプリケーションの設定に合わせてください。** 今回だと[PythonコードとDockerfileで80番ポートを指定している](https://qiita.com/e52yamada/items/4ec8080b9b4ab723ebfd)ため、80を入力します  

![image (16)-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/8e18a4fa-4543-dea8-58e5-9a32d04a91d0.png)  
  
- 「デプロイ」ボタンをクリックするとデプロイがはじまります。デプロイが成功すればステータスが「Running」になり、アプリケーションへアクセスできます。今回のアプリケーションだとデプロイに4,5分ほどかかりました。  

![image (17)-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/562329f8-7ab0-8595-5d02-8e70bbbfa357.png)


## サービスの確認
「デフォルトドメイン」のリンクをクリックすると、Webアプリケーションが動作して「Hello world」が表示されることが確認できました。  

![image (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261789/767a1f45-ae84-cdc5-5845-3424a4d290c0.png)

---
この記事はここまでとなります。
【初心者🐘】PHP入門 (1) 〜PHPの書き方〜

## はじめに
この記事はPHP初心者の私が、アウトプットするために書いたものです。基礎中の基礎の内容から始まりますので、温かい目で見守ってください☺️

今回はPHPの書き方についてまとめました！

## 環境
MAMPをインストールし、エディタはVScodeを使用します。

## PHPの書き方
### 1. 基本的な書き方
```php
<?php

処理

?>
```
- 行の最後に必ず`;`が必要
- `?>`の部分を省力して書くことが可能。省略した場合、`<?php`以下は全てPHPの処理になる
:::note warn
HTMLと一緒に書く際は、`?>`で閉じることを忘れずに！
:::

### 2. 出力方法
PHPで出力させるには、`echo`を使う。
```php
<?php
echo "test"; // => test
```

### 3. バージョンの確認
下記の記述でPHPのバージョンを確認できる。
```php
<?php
phpinfo();
```
![スクリーンショット 2024-12-27 0.06.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557671/5b07a5b4-d37c-2264-d152-faf5cf2e2640.png)

### 4. HTMLの中にPHPを記述
PHPはHTML内で記述することが可能。
```php
<!DOCTYPE html>
<head></head>

<body>
  こちらはHTML

  <?php
  echo "こちらはPHP";
  ?>

</body>
</html>
```
このように表示されます。
```text
こちらはHTML こちらはPHP
```

### 5. 数字と文字
数字は**半角**、文字は`''`か`""`で囲む。

### 6. コメント
1行の場合は`//`、複数行の場合は`/* ... */`
```php
// コメント

/* 
PHP
Qiita */
```

### 7. 改行
改行の書き方は下記の通り。
```php
echo "こんにちは";
echo "<br>" ;
echo "PHPを勉強中です";
```
このように表示される。
```text
こんにちは
PHPを勉強中です
```

## 次回
https://qiita.com/yuto99999/items/92341043e42aa8e3cf00
ユーザーCSSで見出しと箇条書きのレベルを見やすくする (Stylus)

markdownで書かれた記事について
見出し(`h1`～`h6`)がぐちゃぐちゃだったり
箇条書きが深すぎたり
構造が分かりにくくてキレたから書いた

見出しの強さで文字の太さが変わるより`#`が表示されててくれたほうがいい

## ブラウザ拡張(Stylus)を入れておく

[Stylus - Chrome ウェブストア](https://chromewebstore.google.com/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?hl=ja&pli=1)

昔はブラウザにデフォルトでそういう機能あった気がするけどなぜなくなったのか

## CSSをぶち込む

Stylusのアイコンをクリックして絞り込みを「すべて」か、好きなurlにして保存

```css
h1 {
    --mark: "# "
}
h2 {
    --mark: "## "
}
h3 {
    --mark: "### "
}
h4 {
    --mark: "### # "
}
h5 {
    --mark: "### ## "
}
h6 {
    --mark: "### ### "
}

:is(h1, h2, h3, h4, h5, h6):before {
    content: var(--mark);
    font-size: 0.8rem;
    display: inline-block;
    font-family: 'Courier New', Courier, monospace;
    opacity: 0.4;
    margin-right: 4px;
}

ul,
ol,
blockquote {
    border-radius: 10px 0px 0px 10px;
    background-color: rgba(100, 100, 100, 0.08);
}
```

見出しの左側に`#`が表示される。
箇条書きは深さで色が濃くなる。(暗くしていきたいなら100を0にする)
適当だからサイトによってレイアウト崩れるけど気にしないこと (崩れていいサイトで使えば)

## サンプル

https://chatgpt.com/share/676d75cf-9f50-800e-9f34-75b2b0810f72

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/b16767f8-7dbf-ef67-5d93-ff0d3081685c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/6198eac1-dcfa-2124-79ea-16c3fdac535d.png)

悪くない
TC001 のバッテリー残量が一定値以下になったら警告表示を行う

## リチウムイオンバッテリーを積んでいるので…
Ulanzi TC001 はリチウムイオンバッテリーを搭載している。常時電源を繋ぎっぱなしにするとバッテリーの劣化を招きかねない。そのため定期的に電源を外して放電しつつ運用するつもりだが、放っておくと電池切れを起こしてしまう。
電池残量の表示もできるが、1画面分を使ってしまうのはもったいないため、一定値以下になったら警告表示を行うことで代替したい。

## 癖のある残量データ
電池残量については、 Awtrix が10秒毎に MQTT で配信する `stats` の `bat` に整数値(%)で記される。
残量表示がまともであれば、20%や10%で警告表示を行えばよいだろうか、 TC001 の残量表示は癖があり、自分の場合は36%くらいで電源が落ちた。

Awtrix でも同様の指摘がなされているようだ。 55～60% で電源が落ちたと報告している人もいる。
充放電時バッテリー生データ値(`bat_raw`)の最大値・最小値を `dev.json` に記録してその値をもとにバッテリー残量を求めるみたいな話が出ているが、実装されているかは確認できていない。

https://github.com/Blueforcer/awtrix3/issues/391

とりあえず、自分の環境では `bat` の値が40%を下回ったら警告表示をすることにする。

## Node-RED で実装
フローと各ノードは下記の通り。
![tc001_battlow1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/8b619f49-bc98-0865-3d7b-8f95334746b3.png)
![tc001_battlow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/412d682d-f2a1-f28f-4be1-0f20ca50d893.png)
![tc001_battlow3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/d9c89c7f-4543-5aff-fe1e-f7eb34584796.png)
![tc001_battlow4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/ac185dd2-e05c-3ddc-21c5-433109c85568.png)
![tc001_battlow5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/807bffc9-30c8-134e-7ec3-e22f85bb115e.png)
mqtt in ノードで stats の情報を入力し、 switch ノードでバッテリー残量40%未満を分岐。 function でメッセージを作り、 mqtt out で notify トピックに送り込む。
notify は TC001 がそれを受け取った時点で1回のみ表示。 `"hold": true` と指定すれば、本体ボタンが押されるまで表示し続けることが可能。
今回は hold 指定をしていない。この場合、 stats が10秒毎に送られてくるので、 <font color="#FF0000">BATT LOW</font> を5秒表示（各アプリの表示時間設定と同じ）→元の表示に戻って5秒→バッテリー残量40%未満なら再び BATT LOW を5秒表示と交互に表示され続ける。
一度電源に繋いでしまえば一気にバッテリー残量が上がるので、程なくして <font color="#FF0000">BATT LOW</font> メッセージは消える。
一刻も早く消したければ Node-RED 側で該当フローを無効にすればよい。
![tc001_battlow6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/c20b7d61-e8d2-5f3a-8a13-bf9b9e4afcdc.png)

## MQTT で配信される情報なら同様にメッセージを出せる
Awtrix 表示用に Node-REDから MQTT 配信される情報も同様に mqtt in から拾い上げることができる。
以下のようなフローにすれば、YouTube チャンネル登録者数が○万人に達した時に TC001 へメッセージを表示させることも可能だ。
![tc001_battlow7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/59d3e0f4-a3d5-3ee5-3c43-1f83b70a8e4e.png)
TypeScriptとJavaScript

## はじめに
JavaScriptと同じScriptという名称が入った、TypeScriptというものがあるのを調べていく中でよく見かけました。
Scriptと冠するだけあってJavaScriptと何か関係があるのだろうな、と思い調べました。


## JavaScriptについて簡単な振り返り
JavaScriptとはオブジェクト指向のスクリプト言語の一つで、主にWebページに動的な要素やインタラクティブな機能を追加するために使用されます。ReactやjQuery、Vue.jsなど様々なライブラリやフレームワークがあります。

[JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript)


## TypeScriptとは？
マイクロソフトで開発されたオープンソースのプログラミング言語で、JavaScriptに静的型付けとクラスベースのオブジェクト指向を加えたスーパーセット（既存のものをすべて含んだうえで機能が拡張されている上位互換となるもの）です。なので、TypeScriptで既存のJavaScriptコードをそのまま使用することもできます。また、大規模なアプリケーションの開発のために設計されているようです。

[TypeScript: JavaScript With Syntax For Types.](https://www.typescriptlang.org/)


## JavaScriptとTypeScriptの比較

TypeScriptはJavaScriptを拡張したものだと分かりました。次に両者を比較します。

JavaScriptは動的型付けに対して、TypeScriptは静的型付けです。JavaScriptは変数の型を明示的に指定する必要がないですが、TypeScriptでは変数の型を明示的に指定することが出来ます。

```typescript
// 変数textにstring型を定義する場合下記のように書きます。
let text: string = 'Hello';

// 変数textにstring型以外を再代入すると型エラーになります。
text = 40;
```

また、TypeScriptは型推論機能があり、型を自動で判断してくれます。

```typescript
// 変数aに10を初期値として入力すると、number型と判断してくれます。
let a = 10;
```

これにより、コンパイル時にエラーを検出することが出来ます。

ただし、TypeScriptがコンパイル時にエラーを検出出来るということは、TypeScriptではコンパイルの必要があります。JavaScriptはコンパイルの必要がありません。

また、静的型付けであるため、JavaScriptの高い柔軟性が制限されやすい点も考慮に入れるべきでしょう。

||JavaScript|TypeScript|
|--------------------------|-------------------------------|------------------------------------|
|型付け|動的型付け|静的型付け|
|型推論|なし|あり（自動で判断）|
|コンパイル|必要なし|必要あり（TypeScriptからJavaScriptにトランスコンパイル）|
|柔軟性|高い|静的型付けによって制限されることがある|



## まとめ
TypeScriptはJavaScriptをベースにしたプログラミング言語で、JavaScriptとの互換性や、静的型付けなどによってミスによるエラーを極力減らしたい設計思想があることが分かりました。全体的に大規模プロジェクトにフォーカスした作りとなっており、JavaScriptと比べて保守性が高いことが分かりました。
一方、小規模プロジェクトではその恩恵をあまり受けられず、学習コストも相まってあまり使われないことも理解できました。


## 参考資料
[JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript)
[TypeScript: JavaScript With Syntax For Types.](https://www.typescriptlang.org/)

## 採用拡大中！
アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニア仲間を大募集しています！

少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう！

お問い合わせはこちらから↓
[https://official.assisteng.co.jp/contact/](https://official.assisteng.co.jp/contact/)
XIAO MG24 Sense(Silicon Labs EFR32MG24)をArduinoで触ろう3~センサーを使おう~

XIAO MG24 Sense(Silicon Labs EFR32MG24)をArduinoで触ろう２~BLEを使おう~の続きです。

https://qiita.com/usashirou/items/45d41bbae2c17a0fdff3

今回はセンサを使います。
# ライブラリの追加
ArduinoIDEにライブラリを追加しましょう。
左のツールバーのアイコンをクリックし、__Seeed LSM6DS3__ と入力し __ライブラリ__ を __インストール__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/7a3988c5-941c-b4ac-d3c4-932c1bf3c394.png)
ライブラリをインストール後
__ファイル⇒スケッチ例⇒Seeed Arduino LSM6DS3⇒IMU_Capture__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/583a295b-bfbc-7974-1a2c-7a8cfbb8384f.png)
__➡__ でコンパイル、書込みをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f03f35ab-9367-3d9a-8650-99621de5ab4c.png)
書き込み後、ボードを揺さぶると __シリアルモニタ__ にIMUのデータが表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/cc1c2902-558a-04dd-b00a-f2a1a9d3c796.png)
XIAO MG24 Sense(Silicon Labs EFR32MG24)をArduinoで触ろう２~BLEを使おう~

XIAO MG24 Silicon Labs EFR32MG24をArduinoで触ろうの続きです。

https://qiita.com/usashirou/items/fae5cbf8caefd38d45f2

今回は、BLEを使ってみます。
# プロトコル設定
最初にプロトコルを設定します。
__プロトコル__ は __Matter__ と __BLE__ があります。
今回は、__BLE(Silab）__ を選択します。
__ツール⇒Protocol Stack⇒BLE(Silab）__ を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/7dc944d3-4129-aacc-f03a-32ead9dad577.png)
# プログラム
__ファイル⇒スケッチ例⇒Silicon Labs⇒ble_blinky__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/384c70a3-83b4-0363-cade-9de584d8f24c.png)
__➡__ でコンパイル、書込みをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f03f35ab-9367-3d9a-8650-99621de5ab4c.png)
# スマートフォンから操作する
スマートフォンからデバイスに接続してみましょう。
スマートフォンのアプリケーションに今回は __Light Blue__ を使用しました。
__Blinky Example__ を __Connect__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f07bb3cf-b753-8851-5b1c-81ea74b70743.png)
__Properties：Read,Write__ が __LED__ になります。
これをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/aaf25715-95e7-68fd-d9aa-3d96d223ec75.png)
__Write new Value__ に __1__ を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/5ed8fb8e-df25-7ff7-7b2e-cb1ca21f7687.png)
シリアルモニタに __LED on__ になると共にLEDが点灯すれば通信成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/793a65ae-c2b8-08d1-d5a4-c3d446f3169f.png)
あなたにとって「マナビDXQuest」とは？

# はじめに
12/25に投稿するはずが、色々ありまして今日になってしまいました…申し訳ありません。
昨年書こうと思っていたのですが…Qiitaにすら入っておらず、まごまごしているうちに埋まり、投稿できずでした。

今回は早めに入ったのですが、実際このアドベントカレンダーに投稿する目的「だけ」となってしまいました。

過去のアドベントカレンダーの記事を読ませていただきましたが、けっこう凝った記事を書かれる方が多く、「さて、何を書こうか？」と迷っています。

昨年・今年と2年連続で参加していることを踏まえて、「あなたにとって『マナビDXQuest』とは？」を書いてみようと思います。

:::note warn
おことわり
今回のタイトルにおける答えは人それぞれです。
あくまで私自身の「答え」であることをご留意ください。
:::

# 自分にとって「マナビDXQuest」とは？

ひとえに
**「挑戦できる場」**
と言うことかと思います。

## 理由は？

もっとも「マナビDXQuest」自体、eラーニング然り、PBL方式の演習然り、企業協働然り。
新しい事への挑戦もあれば、答えのない中でどこまで最適解に到達できるかの「挑戦」があるのでは無いかと思います。

その「挑戦」の中に、ともに学ぶ仲間・ライバルがいて、マナビDXQuestで行うこと「以外」（例えば資格試験とかそう）でも体験できることも一つの「挑戦」なのかなと思いました。

もっとも私自身、初めてマナビDXQuestに参加する時もDXは言葉ではある程度わかっていても、実際にどうしたら良いのかがわからず、DXに「挑戦」することをひたすら行いました。（もちろん今年も）

この挑戦を通して、今の仕事に直結しているかどうかはまだ不明ですが、DXに関してほんの少しながら「理解」はできたと思っています。

## では何をやってきた？

- 1年目
主にビジネス課題が中心。（業務最適化や新規事業など）
企業協働についてもビジネス中心だった。（こちらも業務最適化だったかな）

- 2年目
主にデジタル課題中心。（Pythonに触れることで喜びと絶望を感じた）
企業協働は現在進行形で進行中。

簡単に書くとこんな感じです。アッサリし過ぎかもしれませんが、ビジネスにしてもデジタルにしても、今の仕事の中にて得られるエッセンスが多くありました。

## あなたに問いたい。

マナビDXQuestは今年SIGNATEとLife is Tech（LIT）の2社で行われているので一概には言えませんが、プログラム自体ももうそろそろ終盤にさしかかってきたと思います。

今年参加されている方、あるいは去年以前に参加された方もいっぱいいらっしゃることかと思います。

参加された方々は、それぞれタイトルにある「意味」をお持ちかと思います。

そのようなあなたに改めて問います。

<b><font size=6 color="red">あなたにとって「マナビDXQuest」とは何ですか？</font></b>

## おまけ

今回は自身の体験談もありますが、もっとも考えていた「意味」を投稿してみました。
技術的に上達した方もいれば、色々な交友関係を築いた方も、そして仕事に直結して業績を上げた方も、あるいはいずれもまだ発展途中の方もいるかもしれません。

このマナビDXQuestは色々な学びの機会が得られますが、単純に受け身だけではなかなか身に付きません。そこで参加することの「意味」を今一度見直した方が良いかなと思って雑筆ながら書いた次第です。

あなた、そして皆さまの「意味」を少しでも見出して頂ければ幸いです。
【Winter '25】Salesforce 認定 Platform デベロッパー資格を更新した

\
![20241227_0_certification_warning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816889/7f5e081e-40fd-80ec-f2bc-7b51a9b09f20.png)

\
Salesforce 認定 Platform デベロッパーの資格を更新したので、ついでに紹介したい。

# Salesforce 認定資格とは
> Salesforce 認定資格は、
Salesforce 製品を使用する各担当者の役割に必要なスキルを保持していることを証明するグローバル共通資格です。

https://tandc.salesforce.com/home

今回更新したのは以下の２つ。
* [Salesforce 認定 Platform デベロッパー](https://trailhead.salesforce.com/ja/help?article=Salesforce-Certified-Platform-Developer-I-Exam-Guide)
>開発者として 1 ～ 2 年の経験と Lightning プラットフォームに関する 6 か月以上の経験
* [Salesforce 認定 上級 Platform デベロッパー](https://trailhead.salesforce.com/ja/help?article=Salesforce-Certified-Platform-Developer-II-Exam-Guide)
>開発者として 2 年から 4 年、Lightning プラットフォームの 1 年以上の開発経験

個人的には、この求められる経験は大体あっている気がする。これくらい経験があれば自然と取れる。


# Trailhead で資格を更新
Salesforce の認定資格を更新するのは、AWS や Azure の資格ほど大変じゃない。テストセンターに行く必要はないし、費用もかからない。Trailhead という Salesforce の学習サイトで、対象のモジュールを完了させるだけだ。

頻度は１年に１度。

新しい機能について学び、クイズに答え、簡単なハンズオンを実施するだけ。

![2024227_1_modules.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816889/f2cbcb1b-c2d1-cafb-c11d-29534dc682bc.png)
※ 画像では Platform Developer I と書かれているけど、これ一つで II (上級) の方も更新される
<br>

https://trailhead.salesforce.com/content/learn/modules/platform-developer-i-certification-maintenance-winter-25?trail_id=maintain-your-salesforce-certifications

https://trailhead.salesforce.com/

# Apex で Null 合体演算子が使えるようになった
資格更新モジュールで学ぶ機能のうち、目に止まったのは Apex で Null 合体演算子を使えるようになったこと。

```apex
String nonNullValue = a ?? 'default';
```

「nonNullValue には a が Null だったら 'default' が入りますよ」というやつ。

Null 合体演算子を使わないとこうなる。

```apex
String nonNullValue = (a != Null) ? a : 'default';
```

Winter '25 よりも前の [Spring '24 で導入された](https://help.salesforce.com/s/articleView?id=release-notes.rn_apex_NullCoalescingOper.htm&release=248&type=5)。


# Iterable インターフェース

ハンズオンは、**Iterable** インターフェースを実装して、テストするという内容だった。

Iterable は、これを使えば List や Set の反復処理が簡単になりますよ、というもの。
[Winter '24 で導入された](https://help.salesforce.com/s/articleView?id=release-notes.rn_apex_iterator_foreach.htm&release=246&type=5)らしい。

実際のハンズオンではなく、リリースノートの例を紹介しておく。

```apex
public class MyIterable implements Iterable<String> {
   public Iterator<String> iterator() {
      return new Set<String>{'Hello', 'World!'}.iterator();
   }
}
```

```apex
for (String str : new MyIterable()) {
   System.debug(str);
}
```

> Hello
> World!

:::note
Trailhead のハンズオンは、コードが動いても、書き方のちょっとした違いでクリアできたりできなかったりする。もし正しいはずなのにクリアできない場合、`this.` が余計かもしれない。
:::

更新完了
---
クイズとハンズオンをクリアすれば更新完了！

![20241226_2_update_completed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816889/78c6798c-c810-8289-c324-0047a9b7d48c.png)

# 感想
この記事を通して、Salesforce 資格について少しでも知ってもらえていたら幸いだ。
<br>
Salesforce 開発の実務から離れた今でも、１年に１度くらいは触れてみるのも悪くない。

１年のうちに様々な機能がリリースされるが、資格更新モジュールを見て初めて「こんなんあったんだ」と気づくものも意外とあり、現役の時はありがたかったのを思い出した。