OmniAICreator/Qiita-1.07M huggingface dataset:
相対論的力学・電磁気学まとめ


新年初日に物理をやるとこの一年の全ての授業で優上を取れるらしいので書いてみました[^1]．相対論的電磁気に関する諸事実についてまとめます．また色々更新します（やる気も暇も全くありませんが笑）．
[^1]: んなわけないだろ

----
$$
\renewcommand{\ds}[0]{\displaystyle}
\renewcommand{\bm}[1]{\boldsymbol{#1}}
\renewcommand{\fvec}[4]{\begin{pmatrix}#1\\ #2\\ #3\\ #4\end{pmatrix}}
\renewcommand{\dif}[2]{\frac{\mathrm{d}#2}{\mathrm{d}#1}}
\renewcommand{\pdif}[2]{\frac{\partial #2}{\partial #1}}
$$
- 慣性系間相対速度：$\beta_\bm{v}=\ds\frac{\bm{v}}c$
- Lorentz因子：$\gamma_\bm{v}=\ds\frac1{\sqrt{1-\beta_\bm{v}^2}}$
- Minkowski計量テンソル：$\eta_{\mu\nu}=\eta^{\mu\nu}$，
```math
\eta_{\mu\nu}=\begin{pmatrix}1&0&0&0\\ 0&-1&0&0\\ 0&0&-1&0\\ 0&0&0&-1\end{pmatrix}
```
- Lorentz変換テンソル：$\Lambda^{\\;\mu}_\nu$，慣性系間相対速度が$x$方向のみの場合，
```math
\begin{pmatrix}\gamma_v&-\gamma_v\beta_v&0&0\\-\gamma_v\beta_v&\gamma_v&0&0\\0&0&1&0\\0&0&0&1\end{pmatrix}
```
- 固有時間：$\tau=\ds\frac{t}{\gamma_\bm{v}},(c\tau)^2=x^\mu x_\mu=(ct)^2-\bm{x}^2$
- 相対論的速度：$u^i=\ds\dif{\tau}{x^i}=\dif{\tau}{t}\dif{t}{x^i}=\gamma_\bm{v}v^i$
- 相対論的エネルギー：$E=m\gamma_\bm{v}c^2=\sqrt{m^2c^4+\bm{p}^2c^2}=mc^2+E_\mathrm{K},E_\mathrm{K}=mc^2(\gamma_\bm{v}-1)$
- 相対論的運動量：$p^i=m\gamma_\bm{v}v^i=mu^i$
- 相対論的力：$f^i=\ds\dif{\tau}{p^i}=\dif{\tau}{t}\dif{t}{p^i}=\gamma_\bm{v}\dif{t}{p^i}$
- 微分ベクトル：$\partial_\mu=\ds\pdif{x^\mu}{},\partial^\mu=\eta^{\mu\nu}\partial_\nu$
- 四元ベクトル：$A^\mu=\Lambda_{\nu}^{\\;\mu}A^\nu,A_\mu=\eta_{\mu\nu}A^\nu,A_\mu=\Lambda^\nu_{\\;\mu}A_\nu$
- 四元位置ベクトル：$\fvec{x^0}{x^1}{x^2}{x^3}=\fvec{ct}{x}{y}{z}$
- 四元速度ベクトル：$u^\mu=\dif{\tau}{}x^\mu=\begin{pmatrix}c\gamma_\bm{v}\\ u^i\end{pmatrix}$
- 四元運動量ベクトル：$p^\mu=\begin{pmatrix}E/c\\ p^i\end{pmatrix}$
- 四元力ベクトル：$f^\mu=\dif{\tau}{}p^\mu=\gamma_\bm{v}\begin{pmatrix}\frac1c\dif{t}{E}\\ f^i\end{pmatrix}$
- 四元電流密度ベクトル：$J^\mu=\begin{pmatrix}\rho c\\ \bm{j}\end{pmatrix}$
- 四元電磁ポテンシャルベクトル：$A^\mu=\begin{pmatrix}\phi/c\\ \bm{A}\end{pmatrix}$
- 四元波数ベクトル：$k^\mu=\begin{pmatrix}\omega/c\\ \bm{k}\end{pmatrix}$
- 電磁気テンソル：$F^{\mu\nu}$，
```math
F^{\mu\nu}=\begin{pmatrix}0&-E_x/c&-E_y/c&-E_z/c\\ E_x/c&0&-B_z&B_y\\ E_y/c&B_z&0&-B_x\\ E_z/c&-B_y&B_x&0\end{pmatrix}
```
- Lorenzゲージ：$\nabla\cdot\bm{A}+\frac1{c^2}\pdif{t}\phi=0$
今までの業務にて経験したこと

広く浅く今まで触れてきたが、これよりは深く利用するようにキャリアを積んで行く予定。

# プログラミング言語
1. C
組み込み開発プロジェクトの際に利用
1. C#
デスクトップアプリの開発プロジェクト時に利用
1. HTML,CSS,JS,PHP
Webサービス開発プロジェクト時に利用

# 開発ツール
1. eclipse
1. Visal Studio 
1. PhpStorm
1. Visual Studio Code

# ツール
1. Redmine
1. Redmine
1. Backlog

※本内容について後日更新を予定しています。
Requirements on Security Extract Template, AUTOSAR 979, R23-11, FO

AUTOSARが2023年版、R23-11を公開しました。
https://www.autosar.org/fileadmin/standards/R23-11/FO/AUTOSAR_FO_RS_SecurityExtractTemplate.pdf

R22-11
https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_RS_SecurityExtractTemplate.pdf

R21-11
https://www.autosar.org/fileadmin/standards/R21-11/FO/AUTOSAR_RS_SecurityExtractTemplate.pdf

R20-11
https://www.autosar.org/fileadmin/standards/R20-11/FO/AUTOSAR_RS_SecurityExtractTemplate.pdf

R19-11
https://www.autosar.org/fileadmin/standards/R19-11/FO/AUTOSAR_RS_SecurityExtractTemplate.pdf

文書は検索してダウンロードできます。
https://www.autosar.org/


<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# Release Overviews

AUTOSARには現在3つの分類があります。Foundation, CAN OSEK/VDXのClassic Platform, Ethernet/TCP/IP POSIXのAdaptive Platform.

Foundation Release Overview, AUTOSAR 781, R23-11, FO
https://qiita.com/kaizen_nagoya/items/f249bdb8c313d8bff883

Classic Platform Release Overview, AUTOSAR No.0 ,R23-11, CP
https://qiita.com/kaizen_nagoya/items/9d22c8722cbc0f42b137

Adaptive Platform Release Overview, AUTOSAR 782, R23-11, AP
https://qiita.com/kaizen_nagoya/items/13a104606a34fe24fcf7

# Qiita 記事一覧


Autosar Foundation R23-11 一覧
https://qiita.com/kaizen_nagoya/items/c30674cb2dac2fcbbd04

AUTOSAR Adaptive Platform R23-11一覧
https://qiita.com/kaizen_nagoya/items/1dece8799a730367b0dc

Autosar Classic Platform R23-11 一覧
https://qiita.com/kaizen_nagoya/items/f770f6c2906e1dcbf180

# 文書変更(Document Change) 
>• No content changes

ファイル名の変更はある。

https://qiita.com/kaizen_nagoya/items/983e1b081ac27509caad

# 用語(terms)
nothing

# References
[1] Standardization Template AUTOSAR_FO_TPS_StandardizationTemplate
[2] Main Requirements AUTOSAR_FO_RS_Main


Glossaryも掲載しましょう。
https://www.autosar.org/fileadmin/standards/R23-11/FO/AUTOSAR_FO_TR_Glossary.pdf



## 補足資料（Additions）
祝休日・謹賀新年：2024年の目標
https://qiita.com/kaizen_nagoya/items/b659d922327a7dcdc898

2023 Countdown Calendar 主催・参加一覧
https://qiita.com/kaizen_nagoya/items/c4c2f08ac97f38d08543

CountDownCalendar月間　いいねをいただいた記事群　views　順
https://qiita.com/kaizen_nagoya/items/583c5cbc225dac23398a

Countdown Calendar 2023, 百記事目を書くにあたって。
https://qiita.com/kaizen_nagoya/items/45185a04cfd88b71256a

1年間をまとめた「振り返りページ」＠２０２３
https://qiita.com/kaizen_nagoya/items/bcd1ebd49d3a9e8c7a90

AUTOSAR 文書番号
https://qiita.com/kaizen_nagoya/items/8b894228a0b76c2265c7

AUTOSAR Countdown Calendar 2023
https://qiita.com/advent-calendar/2023/autosar

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.


# 文書履歴(document history)
ver. 0.01 初稿 　20240101
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
2024年気になる通信業界トレンド（後半） 

さて、[前半戦](https://qiita.com/Assie61400886/items/9349fd509e82a7ac79b6)に続き後半戦いきます。
<br>
6.生成AI/ LLM<br>昨年はChatGPT旋風で生成AIブーム来ましたね。秋のTM ForumのDTWのイベントも一面AIで通信業界もAIブームです。
生成AIによるコンテンツ作成は中国では規制が入っているのもあり中国勢が手を出しづらそうなので、日本勢・欧米勢の頑張りが期待されるところです。では、生成AIがカスタマーサービス等に活用されるかというと出力結果に担保が取れないのでいきなりはないかなーと思って、まずはエンタメ的に「AIで～を作ってみよう！」といったサービスから開始されてます。
LLＭ自体の開発に関しては、Make or Invest的な流れになっていて、日本勢(NTT)は独自開発をアナウンスしていて2024年3月に商用化予定ですが、韓国のSK TelecomはUSのスタートアップに100MUSD投資してLLMを作ると発表した後、ドイツテレコムとパートナリングして通信業界に特化したLLMの開発を打ち出してきました。China TelecomもChatGPTみたいなサービスを提供しますとアナウンスしていますがまだまだ欧米の通信事業者は対応を発表していないのでどう出てくるか楽しみです。買収かスタートアップに投資でしょうかね。
<br>
<br>
7. Web 3.0/ NFT<br>NFTは一昨年から去年にかけて流行って、日本のオペレータもKDDIとかがaU wallet, aU marketとかを春にリリースして、先日China MobileがNFTマーケットプレースをリリースしてプラットフォームとしては整ってきました。一方でNFT自体がまだまだ普及しない。。アメリカはNFT 10%超えしてますが日本は5%切っていて、そもそも金融リテラシーがアメリカと日本ではだいぶ違うしその辺が更に普及のネックかもなーと思っています。
今年もリリースは続くとは思うのですが、マスアダプションが課題です。。(Metaverseと同じですね。。)
<br>
<br>
8. Sustainability/ Circular Economy<br>2023年は私が知る限り初めてTelco Sustainability Forumが行われてESG投資の流れだったりCOP28だったりでSustainabilityの流れが大きくフォーカスあたってます。
日本のオペレータはSustainability対応として再生エネルギーの利用を全面に出していて、自分たちが持っているエネルギー会社からのエネルギー供給を中心にして対応を前に出してます。大きな流れとしては、リサイクル・リユースのところが去年は大きく前に出て、国連とベンダとオペレータとのジョイントでネットワーク機器の回収・リサイクルをするというニュースが台湾やアフリカで出ました。その他3Gの停波や技術革新による電力消費量の削減とうたってますね。そういう意味で（？）IOWNだけでなく、PSTNマイグレもある意味Sustainability対応と言えますかね。。？あと個人的には低軌道衛星猛烈な数で打ちあがってますがあれの回収(Circular性)がとても気になっています。
<br>
<br>
9. 地政学リスク<br>ウクライナ問題が勃発してからヨーロッパの電力供給問題が起こったわけですが、今年の大きなイベントは多発する大統領選です。そう、台湾とアメリカです。
台湾はTSMCに代表されるように半導体の中心地になっているので、台湾が中国より政権になると米国制裁が飛んできて半導体や部品の供給に影響が出る可能性あります。同じくアメリカ大統領選の結果でトランプになると対中がまた厳しくなる可能性あるので中国ベンダ制裁が再び起こる可能性もあります。各国の対中政策がどうなるのか、今年は要注意です。ちなみに地政学リスクかはわかりませんが去年は北米のオペレータの投資が冷え込んだのが大きく各通信ベンダの収益にインパクトを与えて北米リスクすごかったです。今年はそろそろ北米の投資抑制が収まるか、、、？
<br>
<br>
10. どうなるIOWN<br>去年はIOWN第一弾としてAPN発表されましたね。OTN(光装置)スライシングみたいなものだなーと理解してます。IOWN ForumにKDDIも参加したり、ITUでIOWNの仕様策定の話が始まりそうだったり仲間づくりのところも着実に進んできて2030年に向けて進んでいます。一方でまだまだ私にはよくわからないところがあり、固定ネットワークって収益性がとても厳しいのに新規技術の導入ってどういう費用回収計画立てるのかなとか、今ってIPネットワークのほうにインテリジェンスがあるのでAll光ってどういう経路最適化とか加入者制御なんだろう？とか色々計画をもっと聞いてみたいなと思います。果たして日本技術復活になる。。。のか？そういえば半導体も日本技術復活目指すって言ってたけど、本当か。。。？
<br>
<br>
そのほかにもドローンの通信業界への適用系、周波数オークション、ＮＴＴ法、セキュリティ対策、ネットワーク障害対策(日本の場合ローミング)、Dx(特に地方？)等々気になる動向はいっぱいです！
ちなみに私的一押しは中東のEtisalatとSTCの海外オペレータの買収快進撃がどうなるかです。タイのTrue/DTACも合併したし業界再編が続いたり不景気感ある中で今年のイケイケドンドン感がどうなることやら。

以上　とても私見も混ざってますが、お役に立てればです。読んでくれてありがとうございました。
GoとテストとインプロセスDB（GoCon mini 2023 in KYOTO）

去る12月2日に京都で開催されたGo Conference mini 2023 Winter IN KYOTOにて、 「GoとテストとインプロセスDB」という発表(LT)をしてきました。

https://makiuchi-d.github.io/2023/12/31/goconmini2023-in-process-db.ja.html
【Next.js】Imageコンポーネントで画像のロード中にスケルトンスクリーンを表示する方法

以下のように記述することでImageコンポーネントに設定した画像のロード中にスケルトンスクリーンが表示されます。

```jsx
import Image from 'next/image'

function skeleton(w: number, h: number) {
  return `
    <svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <linearGradient id="g">
          <stop stop-color="#d1d5db" offset="20%" />
          <stop stop-color="#f3f4f6" offset="50%" />
          <stop stop-color="#d1d5db" offset="70%" />
        </linearGradient>
      </defs>
      <rect width="${w}" height="${h}" fill="#d1d5db" />
      <rect id="r" width="${w}" height="${h}" fill="url(#g)" />
      <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
    </svg>`
}

function toBase64(str: string) {
  if (typeof window === 'undefined') {
    return Buffer.from(str).toString('base64')
  } else {
    return window.btoa(str)
  }
}

export function Avatar({avatarUrl, name}) {
  return (
    <Image
      src={avatarUrl}
      alt={name}
      width={128}
      hight={128}
      placeholder={`data:image/svg+xml;base64,${toBase64(skeleton(128, 128))}`}
    />
  )
}
```

https://nextjs.org/docs/app/api-reference/components/image#placeholder
RAMAnimatedTabBarControllerライブラリを使用時に真ん中のタブから始める方法(.selectedIndex)

### できなかった経緯
StoryBoard上でUITabBarControllerのClassをRAMAnimatedTabBarControllerに設定していたことにより、コード上でselectedIndexプロパティにアクセスできなかった


### 結論
新たにCustomTabBarController.swift等を作り、その中で読み込みたい外部ライブラリを継承してあげる。

### やり方
1.StoryBoard上でTabBarControllerを作成する。
![スクリーンショット 2024-01-01 22.44.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/ea214c69-ec2e-c2f8-f0a6-8f13f1e0a6bc.png)
2.TabBarController用の.swiftファイルを作成する
![スクリーンショット 2024-01-01 22.49.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/c419d6b1-17e7-71d3-2a1b-2633da127e7d.png)
3.名前は任意でつける(今回はCustomTabBarController)
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333636303933392f34663864623064632d643931342d343066632d623562362d3435363566616235643530302e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/3509f159-28cf-2b2f-8f59-14c02ff8a259.png)

4.作成したCustomTabBarControllerを下記の様に編集
ここに、今回使用したい外部ライブラリ(RAMAnimatedTabBarController)を記述する。
こうすることにより、通常通りselectedIndexプロパティにアクセスが可能。
```swift
// CustomTabBarController.swift
import RAMAnimatedTabBarController

class CustomTabBarController: RAMAnimatedTabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        selectedIndex = 1 // 左から2番目のタブから始める
    }
    
}
```
4.TabBarControllerを選択し、Xcode右側>ShowTheIdentityInspector>CustomClassより
Classに先程作成したClassを選択(CustomTabBarController)
![スクリーンショット 2024-01-01 22.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/65c314f1-970d-4f31-61dd-bf159f399272.png)

### 参考
ChatGPT
Vite+ReactのプロジェクトをGitHub Pagesにデプロイする

以下のページに従ってVite+Reactプロジェクトを作成したあと、そのページをGitHub Pagesにデプロイする方法を書いておきます。
https://ja.vitejs.dev/guide/

# 前提
ローカル上ではViteプロジェクトを動かせている、すなわち`npm run dev`で起動したらlocalhost上でアクセスできる状態にあるとします。


# gh-pages のインストール

まずgh-pagesというライブラリをインストールしておきます。このライブラリはGitHub Pagesのデプロイ手順を自動化してくれるものです。

```
npm install gh-pages --save-dev
```

# スクリプトの設定
`package.json`にスクリプトを設定します。`dist`はビルドされたファイルの出力先です。

```json:package.json
{
  ...
  "scripts": {
    ...
    "deploy": "gh-pages -d dist"
    ...
  },
  ...
}

```

# リポジトリの設定
`vite.config.js（vite.config.ts）`の`base`にGitHubのリポジトリ名を設定します。
もし既にGitHub上にリポジトリが存在しているならその名前を設定します。そうでないなら好きな名前をつけられますが、後ほど作成するリポジトリにも同じ名前をつけます。今回は`react-test`とします。スラッシュを忘れないようにしてください。


```typescript:vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  base: '/react-test/'
})

```

# ビルド&デプロイ
プロジェクトディレクトリでビルドとデプロイを実行します。
```
npm run build
npm run deploy
```

# GitHubリポジトリの作成+プッシュ
ビルドされたファイルをGitHubのリポジトリにプッシュします。まだ作成していない場合はここで作成してください。その際名前は`vite.config.ts`の`base`と揃えます。今回は`react-test`とします。
特別な手順は必要なく、一般的なGitの操作になるのでここでは説明を割愛します。

# GitHub Pagesの設定
作成したリポジトリの`Settings > Pages`を開きます。
`Branch`の項目で`gh-pages`と`/(root)`を選択し、`save`を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643756/10424603-ebf7-5251-6d73-9c3ecf747026.png)

:::note info
`Visit Site`はデプロイ完了後に表示されます
:::

# 公開
セーブすると`Actions`タブでデプロイの様子が見られます。緑色のOKが出たらデプロイ完了です。
完了後に`Settings`を開くと一番上にURLが表示されるので`Visit Site`を押します。
ローカルで表示されたページと同じものが表示されたらデプロイ完了です！

:::note warn
デプロイ完了と出ても数分間は反映されないことがあります。
:::

---
以上で終了です。
ちなみにViteはヴィートと読むらしいですが、どうしても脳内でバイトと読んでしまいます。
【SSH】IPが毎回変わる場合、以前のホストキーが残っているとエラーになる

# 概要
踏み台サーバからEC2インスタンスへアクセスしようとしたら、`WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!`というエラーメッセージが表示されました。本記事では、こちらの原因と解決方法を記載します。

### 前提
アクセスしようとしたEC2インスタンスは、毎日起動・停止を繰り返す設定にしており、その度にプライベートIPが変わるようになっています。ですので、踏み台サーバからアクセスする際は以下のようなコマンドで実施しています。

```
ssh -i sample_ecs.pem ec2-user@{プライベートIPアドレス}
```

# エラー全文

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Please contact your system administrator.
Add correct host key in /home/ec2-user/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/ec2-user/.ssh/known_hosts:22
ECDSA host key for 192.168.10.82 has changed and you have requested strict checking.
Host key verification failed.
```

# 原因は？
このメッセージは、SSHがリモートホストの識別情報（ホストキー）が以前と異なることを検出したときに表示される警告。識別情報（ホストキー）とは何か？というと、SSHが接続先のホストが以前と同じであることを確認するために使用する「暗号化された鍵のペアの一部」で、`known_hosts`ファイルに保存されています。

（これが変更されると中間者攻撃（Man-in-the-Middle attack）の可能性があるので、エラーメッセージにもそのように表示されています）

そして一度保存された後、たまたま同じIPアドレスのホスト（上記の場合`192.168.10.82`）でアクセスしてしまったため、以前のIPアドレスに関連付けられたホストキーと新しいIPアドレスに関連付けられたホストキーが異なるよ、中間者攻撃の可能性あるかもよ？という事態になってしまったのです。

ググってみると、「IPアドレスの振り直しやOS再インストールなどで公開鍵が変わってしまった場合、このようなエラーメッセージが出る」という記事がいくつかあったので、そのようなケースに生じる場合もあると思います。

## 解決策は...
以前のIPアドレス（`192.168.10.82`）でアクセスした際に関連付けられた古いホストキーが`known_hosts`ファイルに保存されているので、それを削除してあげれば良いです。

```
vi /home/ec2-user/.ssh/known_hosts
```

エラーメッセージに22行目と記載があるので該当の行を削除。すると、次回接続時に新しいホストキーが`known_hosts`ファイルに追加されます(=新しいIPアドレスに関連付けられたホストキーを再度受け入れることができるようになる)。

これにより、エラーは解決！

私は直接エディタで編集しましたが、`ssh-keygen`コマンドでも可能です。

```
ssh-keygen -R 192.168.10.82
```

上記により、特定のホストに関連付けられたエントリを手動で削除することができます。

### 参考記事

- [「SSHホスト鍵が変わってるよ！」と怒られたときの対処](https://qiita.com/hnw/items/0eeee62ce403b8d6a23c)
- [AWS上でssh接続時の[WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!]エラー](https://cloud5.jp/ssh-host-id-changed-error/)
Python実行環境を配布して、.NETアプリから利用する。

## 目標
 [namedivider-python](https://github.com/rskmoi/namedivider-python)を、Windowsで実行できるようにし、Excelアドインの関数から呼び出せるようにする。

## 課題
 - .NETから呼び出す方法
 - namedivider-pythonを含めたPython実行環境を、ユーザーに配布する。

 ## .NETから呼び出す
 [pythonnet](https://github.com/pythonnet/pythonnet)を利用する。
 
WinPythonを利用するには、次の設定をしないといけないようです。
[Using Python.NET with Virtual Environments](https://github.com/pythonnet/pythonnet/wiki/Using-Python.NET-with-Virtual-Environments)

#### 設定例
```csharp
Runtime.PythonDLL = @"HOGE\python-3.12.0.amd64\python312.dll";

var pythonPath = @"HOGE\python-3.12.0.amd64";
Environment.SetEnvironmentVariable("PATH", $@"{pythonPath};" + Environment.GetEnvironmentVariable("PATH"));
Environment.SetEnvironmentVariable("PYTHONHOME", pythonPath);
Environment.SetEnvironmentVariable("PYTHONPATH ", $@"{pythonPath}\Lib");

PythonEngine.Initialize();
using (Py.GIL())
{
}
```

設定は、
[C# initialize fails if a class derived from IEnumerable and IEnumerator is in global namespace](https://github.com/pythonnet/pythonnet/issues/1601)
を参考にしています。

#### 名前分割
```csharp
using (Py.GIL())
{
    var name = "佐藤始";
    dynamic namedivider = Py.Import("namedivider");
    dynamic basic_divider = namedivider.BasicNameDivider();
    dynamic result = basic_divider.divide_name(name);
    dynamic family = result.family;
    dynamic given = result.given;
    Console.WriteLine(family + " " + given); //佐藤 始
    Console.ReadKey();
}
```

## Python実行環境を、ユーザーに配布

ユーザーに、Pythonをインストールしてもらい、必要なライブラリもインストールしてもらうのはハードルが高いです。
さまざまな方法を検討し、[WinPython](https://winpython.github.io/)を利用することにしました。
`WinPython`は、ポータブルとして利用できるので、フォルダごとファイルを配置するだけで、Pythonを利用できます。

#### 何をダウンロードするか？
例えば、[WinPython 2023-04 of December 7th 2023](https://github.com/winpython/winpython/releases/tag/7.0.20231126final)なら、`Winpython64-3.11.6.0dot.exe`や、`Winpython64-3.12.0.1dotb5.exe`で良いです。

解凍後、そのフォルダを適当なところに配置します。ユーザーに配布を前提にするなら、Cドライブのすぐ下あたりに配置してアドインを開発すると良いと思えます。

#### ライブラリのインストール
`WinPython Command Prompt.exe`を実行して、pipで、必要なライブラリをインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/80461514-0cc3-2d21-164f-73cb45546424.png)

画像の例では、最初に、pipをアップグレードしています。
次に、`pip install namedivider-python`で、`namedivider-python`をインストールしました。これに依存するライブラリも自動的にインストールされます。

#### 配置の方針
そして、ユーザーに配布する時は、このフォルダ全体を指定したフォルダに配置するようにします。指定したフォルダに配置するのは、`pythonnet`から呼び出しやすくするためです。
いろいろなやり方があるはずです。

今回は、Wix4でファイルを配置する方法を、試してみました。
[WinPythonを、WiX4で配置する。](https://qiita.com/hiro_t/items/4e05588dc5962fa68030)
Shell: パスワード入力コード例(Linux)

## 概要

あまり流行らないのですが、パスワード生成やパスワード入力がまれに必要になるので、メモ。

## パスワード生成

`pwgen` がランダム生成よりは使いやすい。

```console
$ pwgen --symbols 12 4
ohN&a}cohh5n sa@u3Toom.u2 seiT<ahxaef2 Zoe9bei^vieP
```

特定の文字種が2文字以上や禁止文字があるなど要件が合わない場合は、次のやり方がある。前者のアプローチのほうが難易度が低い。

* 複数個パスワードを生成して要件に満たないパスワードを除外する
* 要件に合う文字種と文字数を満たすように生成し、要件を満たしたらランダムに埋めて、最後にシャッフルする

## パスワード入力(汎用)

* パスワード入力(入力誤りのチェックなし)

    ```shell
    #!/bin/bash
    read -s -p "Password: " NEW_PASSWORD
    echo
    
    if [ -z "$NEW_PASSWORD" ]; then
        echo "ERROR: You have not entered your password. Stop processing." 1>&2
        exit 1
    fi
    echo "PASS: $NEW_PASSWORD"
    ```

* パスワードのタイプミスを検出する

    ```shell
    #!/bin/bash
    NEW_PASSWORD=
    while read -s -p "Password: " NEW_PASSWORD; do
        echo ""
        read -s -p "Re-type new password: " CONFIRM_PASSWORD;
        test "${NEW_PASSWORD}" = "${CONFIRM_PASSWORD}" && { echo; break; }
        echo "ERROR: password verification error"
    done
    ```

## パスワード入力(htpasswd)

### 仕様メモ

* パスワードファイルには複数のユーザーのパスワードを格納できる
* 複数ユーザーを格納できるが `htpasswd` コマンドでユーザーが登録済みかを確認する方法は分からず
    * やるにしてもverifyで適当なパスワードを指定して確認する…ぐらい
* 1ユーザーに限る場合は、パスワードファイルの存在有無で管理したほうが論理を簡略化できる
    * ユーザー作成時は、 `-c` で新規作成する
    * ユーザー削除時は、パスワードファイル自体を破棄する

* パスワードファイルは空で作ったほうが論理はスッキリする
    * パスワードファイルがない状態で、パスワード入力を間違えると空ファイルを作る動作となる

### 実装例

* 対話入力

    ```shell
    #!/bin/bash
    test $# -eq 2 || { echo "ERROR: Invalid argument. : ARG-NUM=$#"; exit 1; }
    SUB_COMMAND=$1
    HTUSER=$2
    HTPASSWD_FILE=".htpasswd"
    
    case "${SUB_COMMAND}" in
    add)
        test -s ${HTPASSWD_FILE} || touch ${HTPASSWD_FILE}
        wc -l ${HTPASSWD_FILE}
        while true; do
            grep -qE "^${HTUSER}:" ${HTPASSWD_FILE} && { echo "WARNING: User already exists : USER='${HTUSER}'"; break;}
            (set -x; htpasswd ${HTPASSWD_FILE} ${HTUSER}) && break
        done
        wc -l ${HTPASSWD_FILE}
        ;;
    
    delete)
        (set -x; htpasswd -D ${HTPASSWD_FILE} ${HTUSER})
        ;;
    esac
    ```

* バッチ処理  
  `-i` オプションで標準入力からパスワードを受け取ることができる。

    ```shell
    #!/bin/bash
    test $# -ne 1 && { echo "ERROR: Invalid argument. : ARG-NUM=$#"; exit 1; }
    HTPASSWD_FILE=".htpasswd"
    
    case $1 in
    create)
        touch ${HTPASSWD_FILE}
    
        while read HTUSER; do
            (set -x; pwgen 12 1 | tee .pass.${HTUSER} | htpasswd -i ${HTPASSWD_FILE} ${HTUSER})
        done <<EOF
    user01
    user02
    EOF
        wc -l ${HTPASSWD_FILE}
        ;;
    
    delete)
        while read HTUSER; do
            (set -x; htpasswd -D ${HTPASSWD_FILE} ${HTUSER})
        done <<EOF
    user01
    user02
    EOF
        ls -l ${HTPASSWD_FILE}
        rm -f ${HTPASSWD_FILE}
        ;;
    esac
    ```
ユニバーサル・プログラミング言語としての自然言語各国語の台頭と日本語プログラミング言語の未来

# はじめに

日頃ご支援・交流いただいておりますみなさま、あけましておめでとうございます。今年もどうぞよろしくお願いいたします。

Qiitaでの本年初投稿記事となりますので、少し日本語プログラミング言語の未来について考えてみます。SF好きなわたしのあくまで憶測で、実現性の妥当性を主張するものではありません。

# ユニバーサル・プログラミング言語としての自然言語各国語の台頭

生成AIの自然言語処理能力が飛躍的に向上した結果、自然言語からのプログラミング言語への変換が実用化されつつあります。

https://ledge.ai/articles/microsoft-ai-programming-translater

https://qiita.com/artisanbaggio/items/167a9e3a13fe045e6657

この記事でいうユニバーサル・プログラミング言語とは汎用目的のプログラミング言語とい意味で、特定用途向けではなくあらゆる開発目的に使えるという意味と、もうひとつは前記の意味での各種の汎用実装言語、C/C++,Java,C#,Go,TypeScript,JavaScript,Python,PHP,Ruby等に対する汎用トランスコンパイラ言語という意味の大きく２つです。

# わたしの思い描く未来

自然言語には各言語の文化由来の自然定義の語義の単語が存在し、それらの意味の多義性、多用性、多態性がまさに言語を単なる人間同士のコミュニケーションツールとしての役割だけではなく、各国語の背景となる文化、文学、詩、歌謡といった芸術の域にまで昇華させる源泉となっているとわたしは考えます。

生成AIの能力が、過去の文化遺産を大規模学習することで、才人が行える芸術的成果物をも出力できるようになりつつあるという面はここでは論じません。

ソフトウェアの設計情報としてのソースコードとしての実装言語の役割は、このような意味の多義性は、存在しても区別できる情報で識別して最終的には一意になる構造を持っており、**設計者が意図した構造を一意に定義する役割**として存続していくと考えております。

つまり、設計者が生成AIにざっくり 自然言語で構想を伝えて、指定した実装言語のなんらかのソースコードが生成された場合、それはあくまでブラックボックス化された処理の結果のため、設計者の意図に沿うか沿わないかは、ある意味ギャンブル性が存続すると考えております。

これは生成AIの自然言語処理能力がどんなに向上しても、**自然言語自体がもつ一意性のなさという構造的な制約が存在**するからです。

# 日本語プログラミング言語はあくまで構造化された形式言語

この意味での日本語プログラミング言語は、自然言語入力のトランスコンパイル先としても存続するとわたしは考えております。生成AIの学習モデルの範囲に日本語プログラミング言語の構文情報が獲得されれば、その他の文字をベースとしたその他のプログラミング言語と同様、日本語プログラミング言語のより厳密なソースコードに変換してもらえるようにもなるでしょう。

また、生成AIへの入力情報としても自然言語より構造化された言語の方がより確度の高いソースコードを生成できることでしょう。現状は生成AIが日本語プログラミング言語の構文を事前学習していないので、覚えさせるところで力尽きます。

https://qiita.com/mylifewithviolin/items/739d5b792f2f9d4e14fc

# おわりに
書き終わってみるとぜんぜんSFっぽくありませんでした。失礼しました。
MediawikiでLuaが動かない場合

Mediawikiを１０年ぶりくらいに構築したのだが、Luaが動かないエラーに散々悩まされたのでメモ

## Luaとは
スクリプト系言語の一種。詳細はリンク先。→　[Lua](https://ja.wikipedia.org/wiki/Lua "Lua")

## Mediawikiでの組み込み
MediawikiにはScribunto拡張のひとつとして組み込まれているが、wikipediaからテンプレートを引っ張ってこようとすると、このLuaの例外が処理できなくて、困った。

## 環境
Xreaサーバ

## ネット上の情報
さくらのインターネットサーバにおけるLuaの有効化記事は、何本か[見つけた](https://vanguardflight.xii.jp/wp/2014/03/30/313/ "MediaWikiにExtension:Scribuntoをインストール")のだが、Xreaはあいにく、そこまで本格的ではないと（個人的には）思っているので、ディレクトリを再検分。LuaのExtensionの組み込みの中にモジュールが入っていた。

## Path
（Path to Mediawiki）/extensions/Scribunto/includes/Engines/LuaStandalone/binaries

## 有効化
Path配下にある、OS毎に区切られたバイナリーに「755」を付与するとLuaが動き出した。
KVM/QEMU Windowsゲストドライバ(virtio-win)のインストール

 #### ホストマシンでの virtio ドライバーインストールメディアの準備
 
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_virtualization/optimizing-windows-virtual-machines-on-rhel_installing-and-managing-windows-virtual-machines-on-rhel#installing-kvm-drivers-on-a-host-machine_installing-kvm-paravirtualized-drivers-for-rhel-virtual-machines

#### Windows ゲストへの virtio ドライバーのインストール
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_virtualization/optimizing-windows-virtual-machines-on-rhel_installing-and-managing-windows-virtual-machines-on-rhel#installing-kvm-drivers-on-a-windows-guest_installing-kvm-paravirtualized-drivers-for-rhel-virtual-machines
【SwiftUI】sheetで表示したViewだとKeyboard上のToolbarが機能しない（iOS17.0）

# はじめに
iOS17.0でキーボードの上にボタンを表示しようとしても表示されないという問題があるようです。
過去にも同様のバグがあったようですが、iOS16で1度修正されて、iOS17.0で再発したっぽいです。
iOS17.2では直ってました。

https://ja.stackoverflow.com/questions/89652/sheet%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%95%E3%81%9B%E3%81%9F%E9%9A%9B%E3%81%AB-%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AEtoolbar%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84

https://developer.apple.com/forums/thread/709227

再現方法を記録しておきます。

# サンプルアプリ
|iOS17.0|iOS17.2|
|-|-|
|![Simulator Screen Recording - iPhone 15 - 2024-01-01 at 20.30.30.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/cdc3d4a1-244c-2288-9aad-f837f6609d35.gif)|![Simulator Screen Recording - iPhone 15 - 2024-01-01 at 20.37.19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e4e8adb2-6523-d97c-f892-f7da203b4b18.gif)|

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State var isSheetPresented = false

    var body: some View {
        Button {
            isSheetPresented = true
        } label: {
            Text("sheetを表示")
        }
        .sheet(isPresented: $isSheetPresented) {
            SubView()
        }
    }
}

struct SubView: View {
    @State var text = ""

    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationView {
            TextField("", text: $text)
                .textFieldStyle(.roundedBorder)
                .padding(20)
                .toolbar {
                    ToolbarItemGroup(placement: .topBarTrailing) {
                        Button {
                            dismiss()
                        } label: {
                            Text("閉じる")
                        }
                    }

                    ToolbarItemGroup(placement: .keyboard) {
                        Spacer()
                        Button {
                            print("完了")
                        } label: {
                            Text("完了")
                        }
                    }
                }
        }
    }
}
```

# 対策
現時点では不明

# おわり
意外と致命的なバグな気がします。
対策を見つけ次第追加します。
UIKitを使えばなんとかなる可能性はありそうです。

https://feedbackassistant.apple.com

Appleにフードバックを送って直してもらいましょう
AWSの「Redshift」「Athena」「EMR」を比較して違いの理解を深めたいっという備忘録

# Amazon Redshift

■用途
データウェアハウス（Data Warehouse）として使用されることが主な目的です。大規模なデータセットの分析クエリやBI（Business Intelligence）ツールからのアクセスに適しています。

■アーキテクチャ
カラムベースのストアエンジンを使用しており、大容量のデータを高速に処理できるように最適化されています。

■データの格納
データは列単位で格納され、クエリパフォーマンスを向上させることが可能です。

■データのロード
大規模なデータセットを一括でロードすることができます。


****特徴****
データウェアハウスとして設計され、高性能な分析用途に特化しています。専用のクラスタを使用し、大量のデータを高速に処理できます。

----------------------
### できること

大規模なデータセットを高速に処理し、データウェアハウスとして使用可能。
カラムベースの格納エンジンを使用してクエリのパフォーマンスを最適化。
テーブル結合、集計、窓関数などの高度なSQL操作が可能。
データの圧縮、ソートキー、分散キーなどの最適化オプションが提供される。

### できないこと:

サーバーレスな形態ではなく、専用のクラスタが必要。
リアルタイムデータ処理には向いていない。
クエリの実行時にリソースが動的に拡張されるわけではない。



# Amazon Athena

■用途
サーバーレスな形態のクエリサービスで、S3に保存されたデータに対してSQLクエリを実行することが可能です。データ湧き上がり型の分析に適しています。

■アーキテクチャ
クエリの際にリソースが自動的に割り当てられ、必要なときにのみコストが発生します。

■データの格納
主にAmazon S3にデータを格納し、Athenaはそこからデータをクエリします。

■データのロード
データはS3に保存され、Athenaはそのデータをクエリ対象として利用します。

****特徴****
サーバーレスなSQLクエリサービスであり、クエリの実行時にのみリソースが割り当てられるため、管理やセットアップが簡単です。S3に格納されたデータに対して即座にクエリを実行できます。

----------------------
### できること

サーバーレスな形態で、SQLクエリをS3上のデータに対して即座に実行可能。
データのパーティショニングやフォーマットの変更などの設定が可能。
複雑なETLプロセスなしにデータにアクセス可能。
クエリの実行時にのみコストが発生するため、コスト効率が高い。

### できないこと

リアルタイム処理には向いていない。
大規模なデータセットの高速な処理にはRedshiftほど効率的ではない。
複雑な分析やデータ変換は、通常は他のツールが必要。

# Amazon EMR (Elastic MapReduce)

■用途
大規模なデータセットを処理するための分散処理フレームワークです。Hadoop、Spark、Hiveなどのエコシステムをサポートしており、異様な処理や分析が可能です。

■アーキテクチャ
分散処理クラスタを構築し、複数のノードでタスクを実行します。異様な処理や機械学習など、柔軟な処理が可能です。

■データの格納
HDFS（Hadoop Distributed File System）などを使用してデータを格納し、処理対象として利用します。

■データのロード
EMRクラスタを使用してデータを処理および分析します。

****特徴****
分散処理フレームワークを提供し、Hadoop、Spark、Hiveなどのエコシステムをサポートします。柔軟性が高く、異様な処理や複雑なデータ操作が可能です。分散処理クラスタを使用して、大規模なデータセットの処理が可能です。

----------------------
### できること

大規模データセットの分散処理と異様な処理が可能。
Hadoop、Spark、Hiveなどのエコシステムをサポート。
機械学習、グラフ分析、リアルタイム処理など多岐にわたるタスクに対応。
### できないこと

サーバーレスな形態ではなく、クラスタの管理が必要。
データの格納にはHDFSなどの分散ファイルシステムが必要。
単純なSQLクエリ処理にはRedshiftやAthenaほど効率的ではない。
各サービスは異なる用途に特化しており、プロジェクトのニーズや要件に応じて最適なサービスを選択することが重要です。


間違ってる、ここはこうじゃない？等々ございましたらご指摘いただけますと幸いです。
2024年の抱負

## はじめに　
現在大学2年生のプログラミングを独学しているものです。最近qiitaをよく見るようになったぐらいのぺーぺーです。みなさんのような投稿はできませんが、このタイミングで心機一転できるように投稿してみようかなーぐらいで投稿します。

## 2023年の振り返り
#### 全体的に振り返って
2023年の10月ぐらいからフロントエンドエンジニアになりたいと決意し、それまでは、大学の勉強をしたり、マーケティングや統計学など薄く色々な分野に触れ、自分は社会にでて何がしたいのかを考えていました。
エンジニア就活するには遅いかもしれませんが、自分のやりたいことを絞れたのは良かったとポジティブに捉えています。

#### フロントエンドの勉強内容
1. UdemyでCodeMafiaさんの[JS]ガチで学びたい人のためのJavaScriptメカニズム
2. ShinCode_Campでプログラミングチュートリアルさんの[Reactアプリ開発]3種類の　　　Reactアプリケーションを構築して、Reactの理解をさらに深めるステップアップ講座

　1の講座でJSの根本を理解し、2の講座でわからないところをチャットGPTやGoogleで調べたりして、Reactでどのようにコーディングしてアプリケーションを作成してしていくのかを学びました。

## 2024の抱負と確実に達成すること
### 抱負
就活に決して手を抜かない

### 確実に達成すること
3月までにポートフォリオの作成し、インターンに受かること。
夏までにハッカソンに参加すること。

## 最後に
やる気を引き出すためにはじめて投稿をしてみました。この業界をまだ全く知りませんが、さまざまなことに触れて知識を蓄えようと思います。

有言実行
expo app　がつながらなくなった


## 事象
expo app　がつながらなくなった

## 原因

>制限的なネットワーク条件 (公衆 Wi-Fi に一般的)、ファイアウォール (Windows ユーザーに一般的)、またはエミュレータの設定ミスにより、lan/localhost 経由でリモート デバイスを開発サーバーに接続することが困難になる場合があります。

ネットワーク条件によるものらしい。恐らくルーターの位置を変えた際に、設定もおかしくなってしまった模様。多分初期化したせい。

## 解決策
トンネリングという方法を用いて、プロキシ URL を介して開発サーバーに接続する。

1. @expo/ngrokのインストール
    ```
    npm i -g @expo/ngrok
    ```
1. トンネルURLから開発サーバを起動
    ```
    npx expo start --tunnel
    ```



## 参考

https://qiita.com/choco_p/items/13900fcfa07df3968302

https://docs.expo.dev/more/expo-cli/#tunneling

https://qiita.com/mininobu/items/b45dbc70faedf30f484e
git rebase の使い所

# 変更内容の取得

例えば、`main` と `develop` ブランチがあるとします。
`main` ブランチの変更を `develop` ブランチに取り込んで、`develop` ブランチをPush、PR を作成して、マージする場合、`rebase` はとても役に立ちます。

図にすると以下のような形です。

## 使い方
現在、`main` ブランチにいると仮定して、remote にある変更内容を local に pull します。

```zsh
git pull origin main
```

次に、develop ブランチへ切り替えます。

```zsh
git checkout develop
```

ここで、`main` ブランチの変更内容を `develop` ブランチに統合します。
これにより、`develop` の変更が、`main` の最新変更の上に再配置されます。

```zsh
git rebase main
```

:::alert note
ここで、CONFLICT が発生した場合、コンフリクトの原因を解決し、変更内容をステージングしたら、以下のコマンドで rebase を続行します。
```zsh
git rebaes --continue
```
:::

rebase が完了したら、変更をリモートの `develop` ブランチに Push します。リベースは履歴を変更するため、通常の Push ではエラーが発生します。そのため、この場合、force push する必要があります。

```zsh
git push origin develop --force
```

### 他にも

今回は rebase の話なので紹介はしませんでしたが、同様なコマンドに、`git merge` があります。
`git merge` にするか、`git rebase` にするかは度々議論になるので、チーム開発などでは要確認することが必要です。


# コミットを1つの commit にまとめたい

## Rebase コマンドの入力
以下のようなコマンドを入力します。

```
git rebase -i [まとめたい commit の範囲]
```

ここで、`[まとめたい commit の範囲]` の値は以下のように場合分けできます。

### 直前(HEAD)から n 個前の commit をまとめたい
ここで、n は自然数です。

```
git rebase -i HEAD~n
```

### HEAD 以外の範囲
## コミットの選択
エディタが開き、選択したコpick 1234567 古いコミットメッセージ
pick abcdef0 次のコミットメッセージ
pick 1a2b3c4 最新のコミットメッセージ
ミットが表示されます。

```vi
pick 1234567 古いコミットメッセージ
pick abcdef0 次のコミットメッセージ
pick 1a2b3c4 最新のコミットメッセージ
```
ここで、まとめたいコミット以外を `pick` -> `squash` に変換します。

```vi
pick 1234567 古いコミットメッセージ
squash abcdef0 次のコミットメッセージ
squash 1a2b3c4 最新のコミットメッセージ
```

保存すると、再度エディタで以下の内容が表示されます。

```vi
# This is a combination of 2 commits.
# The first commit's message is:

古いコミットメッセージ

# This is the 2nd commit message:

次のコミットメッセージ

# This is the 3nd commit message:

最新のコミットメッセージ

# Please enter the commit message for your changes. Lines starting
```

これを最適なコミットメッセージに編集します。
今回は、「最新のコミットメッセージ」にまとめたいので、以下のようにまとめます。

```vi
最新のコミットメッセージ

# Please enter the commit message for your changes. Lines starting
```

これを保存すれば、最新のコミットにまとめることができます。

# rebase を中止したい

```
git rebase --abort
```

で、rebase を中断して元に戻ることができます。
flutterのslangの話



## 良いところ

- 機能が豊富
- 入力フォーマットもメジャーなフォーマットをサポート(json, yaml, csv)
- 最終的にコード化されるのでコーディング中にコード支援をナチュラルに受けられる(参照ミスが直ぐにわかる)

## 悪いところ

- 全言語のデータがコード化されるので巨大なテキストデータがあるアプリの場合は向かない
極端ではあるが、ビルド後が1言語10MBで、20言語対応のアプリだと、200MBの言語コードに…
もしかすると、使用言語だけ読み込めるようにビルドできるかもしれないが、現状出力したコードを見る限りデフォルト設定だとダメそう作りだ。
まあ、それくらい大きいテキスト量であれば、頻繁に使用しないものを言語別アセットにすればよいだけかも。


## slangのデータをCSV(excelやspreadsheet等)で管理する話

### メリット

- データの一覧性が高い(キーの翻訳漏れが目視確認しやすい)
- 言語データは、エンジニア以外も触るので編集しやすい形式が良い
	翻訳業者に依頼した場合に、基本的に受け取ったデータをそのまま使いやすい

### デメリット

- 配列系データの表現が難しい
	調べた範囲では、CSVだけ配列表記方法が分からなかった
	month(map).n1とかmonth.1.nameの様なキーにすれば可能だが出来上がるコードが汚いか、参照の仕方が汚くなる



## サポート言語の一覧の取得について

CSVでこんな感じに定義しているとして

|key|ja|en|
|-|-|-|
|language|日本語|English|

コード側は、こんな感じで一覧を取得する

```example.dart
/// サポート言語名の一覧を取得する
///
/// return List<String> サポート言語名の一覧
List<String> getLanguageNames() {
  // 全言語のインスタンスから各言語のlanguageの値を参照する
  var languageNames = <String>[];
  for(var value in LocaleSettings.instance.translationMap.values) {
    languageNames.add(value.language);
  }
  return languageNames;
}
```
【TIPS】マップリストのアトムキーと文字列キーの相互変換（キーワードリストのリストもついでに）

この記事は、[Elixir Advent Calendar 2023 シリーズ13](https://qiita.com/advent-calendar/2023/elixir) の11日目です

---

【本コラムは、3分で読め、3分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

下記コラムで、マップのアトムキーと文字列キーの相互変換を扱いました

https://qiita.com/piacerex/items/4882e71dc6439f365acf

マップリストでも同様のことを行いたいと思います

元データは下記の通りです

```diff_elixir:アトムキーのマップリスト
users_a = [
  %{id: :id000, name: "hoge", weight: 49}, 
  %{id: :id001, name: "foo",  weight: nil}, 
  %{id: :id002, name: "fuga", weight: 33}
]
```

```diff_elixir:文字列キーのマップリスト
users_s = [
  %{"id" => :id000, "name" => "hoge", "weight" => 49}, 
  %{"id" => :id001, "name" => "foo",  "weight" => nil}, 
  %{"id" => :id002, "name" => "fuga", "weight" => 33}
]
```

ついでに、キーワードリストのリストもアトムキー／文字列キーのマップリストへの変換を行います（元データは下記）

```diff_elixir:キーワードリストのリスト
users_kl = [
  [id: :id000, name: "hoge", weight: 49], 
  [id: :id001, name: "foo",  weight: nil], 
  [id: :id002, name: "fuga", weight: 33]
]
```

# マップリストのアトムキー → 文字列キーに変換

```diff_elixir
iex> users_a |> Enum.map(& Map.new(&1, fn {k, v} -> {Atom.to_string(k), v} end))
[
  %{"id" => :id000, "name" => "hoge", "weight" => 49},
  %{"id" => :id001, "name" => "foo", "weight" => nil},
  %{"id" => :id002, "name" => "fuga", "weight" => 33}
]
```

# マップリストの文字列キー → アトムキー

```diff_elixir
iex> users_s |> Enum.map(& Map.new(&1, fn {k, v} -> {String.to_atom(k), v} end))
[
  %{id: :id000, name: "hoge", weight: 49},
  %{id: :id001, name: "foo", weight: nil},
  %{id: :id002, name: "fuga", weight: 33}
]
```

# キーワードリストのリスト → アトムキーマップリスト

```diff_elixir
iex> users_kl |> Enum.map(& Enum.into(&1, %{}))
[
  %{id: :id000, name: "hoge", weight: 49},
  %{id: :id001, name: "foo", weight: nil},
  %{id: :id002, name: "fuga", weight: 33}
]
```

# キーワードリストのリスト → 文字列キーマップリスト

```diff_elixir
iex> users_kl |> Enum.map(& Map.new(&1, fn {k, v} -> {Atom.to_string(k), v} end))
[
  %{"id" => :id000, "name" => "hoge", "weight" => 49},
  %{"id" => :id001, "name" => "foo", "weight" => nil},
  %{"id" => :id002, "name" => "fuga", "weight" => 33}
]
```
仮想環境別の共有ディスク設定

## 1. ESXi環境の場合
仮想ディスクを共用ディスクとする場合は、以下のどちらかの設定を実施してください。

#### ・マルチライターで共有する(推奨)

１. 共用ディスク用に、以下の設定で新たな `SCSIコントローラ` を追加します。
```
   SCSIコントローラのタイプ：ゲストOSのシステムディスク用のコントローラと同じ
   SCSIバスの共有          ：なし
```
２. データストアに、以下の設定で `仮想ディスク` を作成します。
```
   タイプ                  ：シックプロビジョニング(Eager Zeroed)
   ディスクモード          ：独立型：通常
   共有                    ：マルチライター
   仮想デバイスノード      ：手順1.で作成したSCSIコントローラの任意のID
```

#### ・SCSIバスで共有する
１. 共用ディスク用に、以下の設定で新たな `SCSIコントローラ` を追加します。
```
   SCSIコントローラのタイプ：ゲストOSのシステムディスク用のコントローラと同じ
   SCSIバスの共有          ：仮想(1つのESXiホスト上のゲストOS間クラスタ環境の場合)
                             物理(複数のESXiホスト上のゲストOS間クラスタ環境の場合)
```
２. データストアに、以下の設定で `仮想ディスク` を作成します。
```
   タイプ                  ：シックプロビジョニング(Eager Zeroed)
   ディスクモード          ：独立型：通常
   共有                    ：未指定
   仮想デバイスノード      ：手順1.で作成したSCSIコントローラの任意のID
```
仮想デバイスノードの `コントローラ番号` と `ディスク番号` は、クラスタシステムを構成するすべてのノードで同じになるよう設定してください。

引用元はこちら。
https://software.fujitsu.com/jp/manual/manualfiles/m230005/j2ul2820/02z200/index.html

## 2. KVM環境の場合

KVMゲストで共用ディスクを使用する場合、[共有可能] (shareable)に設定し、[キャッシュモデル]を[none] (cache='none')にしてください。

設定方法は以下のとおりです。

#### virtioブロックデバイスの場合
ゲストOSを停止します。

仮想マシンマネージャから停止したゲストOSを選択し、ツールバーの `Open` ボタンをクリックします。

表示されたウィンドウのツールバーのをクリックし、`ハードウェアの詳細情報` を表示します。

左のハードウェア一覧から、仮想ディスク `VirtIO Disk` を選択します。

`仮想ディスク画面` で、以下の設定を行い、`適用` ボタンをクリックします。

`共有可能` のチェックボックスをチェックします。

`キャッシュモデル` リストから `none` を選択します。

#### virtio-SCSIデバイスの場合
ゲストOSを停止した状態で、管理OS上の `ゲスト設定ファイル(/etc/libvirt/qemu/ゲスト名.xml)` に、以下のように `shareable` と `cache='none'` を記述します。

```
# virsh edit ゲスト名
```
記載例
```xml
<disk type='block' device='lun'>
  <driver name='qemu' type='raw' cache='none'/>
  <source dev='/dev/disk/by-id/scsi-36000b5d0006a0000006a1296001f0000'/>
  <target dev='sdh' bus='scsi'/>
  <shareable/>
  <address type='drive' controller='0' bus='0' target='0' unit='7'/>
</disk>
```

引用元はこちら。

https://software.fujitsu.com/jp/manual/manualfiles/m220000/j2ul2506/02z202/index.html

## 3. Hyper-V環境の場合

iSCSIを利用するしかなさそう(WSFC環境以外の場合）。

https://redmondmag.com/articles/2019/10/30/configuring-a-shared-vhd-in-hyperv.aspx
AstroコンポーネントのProps定義が反映されない場合の解決法の一つ

# 起こった問題

Astroのコードブロック内で`Props`という型を定義すると、そのファイル内で使う外部から渡される値を定義できます（[ドキュメント](https://docs.astro.build/ja/core-concepts/astro-components/#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AEprops)）。

動的ルーティングで用いる`getStaticPaths`と組み合わせることも可能で、以下のように使えます。

```ts
type Props = InferGetStaticPropsType<typeof getStaticPaths>;

export async function getStaticPaths() {
  ...
  return {
    params: { slug: entry.id },
    props: { entry, next, prev },
  };
}

const { entry } = Astro.props;
```

ドキュメントにはこの定義を自動で検出して利用できると書かれていますが、この`Props`の定義がVSCode上で反映されないということがありました。

# 解決法

もとのコードは、`getStaticPaths`の定義を受けて`Props`を定義することを意識して

```ts
export async function getStaticPaths() { ... }

type Props = InferGetStaticPropsType<typeof getStaticPaths>;
```

のように書いていました。
これを冒頭のコードのように、`Props`の定義を`getStaticPaths`より上に持っていくと検出が機能しました。

はっきりと理由を分析したわけではありませんが、`async/await`によりコードの流れが変化することが関係していると思われます。
別のコンポーネントでも、`await`文を伴う関数呼び出しより前に`Props`を定義するように変更したところ正しく認識されるようになりました。
`await`は以降のコードをコールバックに包むので、`Props`の定義をも包んでしまうのかもしれませｎ。

# まとめ

`Props`の定義がエディタ等に検出されない場合、定義を`async/await`の使用より先に持っていくと正しく検出される場合があるようです。
AWSのCloudFrontとCloudFrontディストリビューションの違いについての備忘録

## CloudFrontとは

AWSのコンテンツデリバリーネットワーク（CDN）サービスです。
CloudFrontは、世界中のエッジロケーションに配置されたサーバーを利用して、ユーザーに対してコンテンツを高速に配信することを可能にします。
静的および動的なウェブコンテンツ、APIエンドポイント、動画など、さまざまな種類のコンテンツを高効率かつ低遅延で配信できます。

## CloudFrontディストリビューションとは

「CloudFront Distribution」とは、AWS CloudFrontサービスを使用する際に特定のコンテンツデリバリーの設定や構成を指す言葉です。
CloudFront Distributionは、特定のオリジン（通常はS3バケット、EC2インスタンス、API Gatewayなど）からデータを取得し、エッジロケーションにキャッシュします。
CloudFront Distributionを設定することで、コンテンツの配信設定、キャッシュコントロール、セキュリティポリシーなどを定義できます。

## 違いを簡単にいうと

「CloudFront」はAWSのCDNサービス全体を指し、
「CloudFront Distribution」は特定のコンテンツデリバリーの設定や構成を指します。


間違い、これはこうかな？ みたいな文言等等ございましたらご指摘いただけますと幸いです。
【TIPS】マップのアトムキーと文字列キーの相互変換

この記事は、[Elixir Advent Calendar 2023 シリーズ12](https://qiita.com/advent-calendar/2023/elixir) の10日目です

---

【本コラムは、4分で読め、4分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

Elixirのマップは、キーが、アトムと文字列の2種類使えます

```diff_elixir:アトムキーのマップ
iex> user_a = %{id: :id000, name: "hoge", weight: 49}
iex> user_a.name
"hoge"
iex> user_a[:name]
"hoge"
iex> user_a |> Map.put(:name, "piacere")
%{id: :id000, name: "piacere", weight: 49}
```

```diff_elixir:文字列キーのマップ
iex> user_s = %{"id" => :id000, "name" => "hoge", "weight" => 49}
iex> user_s["name"]
"hoge"
iex> user_s |> Map.put("name", "piacere")
%{"id" => :id000, "name" => "piacere", "weight" => 49}
```

ただし、この2種類の間に互換性が無いため、扱いに困ることがありますので、相互変換の技をまとめておきます

# 文字列キーマップをアトムキーマップに変換

## Map.new ＋ String.to_atom

```diff_elixir
iex> user_s |> Map.new(&{String.to_atom(elem(&1, 0)), elem(&1, 1)})
%{id: :id000, name: "hoge", weight: 49}

iex> user_s |> Map.new(fn {k, v} -> {String.to_atom(k), v} end)
%{id: :id000, name: "hoge", weight: 49}
```

## for ＋ String.to_atom

```diff_elixir
iex> for {k, v} <- user_s, into: %{}, do: {String.to_atom(k), v}
%{id: :id000, name: "hoge", weight: 49}
```

## Jason.encode! ＋ Jason.decode!　※ただし要注意

アトムのバリューが、文字列に変化してしまうので注意

```diff_elixir
iex> user_s |> Jason.encode! |> Jason.decode!(keys: :atoms)
%{id: :id000, name: "hoge", weight: 49}
```

# 文字列キーマップをアトムキーマップに変換

## Map.new ＋ Atom.to_string

```diff_elixir
iex> user_a |> Map.new(fn {k, v} -> {Atom.to_string(k), v} end)
%{"id" => :id000, "name" => "hoge", "weight" => 49

iex> user_a |> Map.new(&{Atom.to_string(elem(&1, 0)), elem(&1, 1)})
%{"id" => :id000, "name" => "hoge", "weight" => 49}
```

## for ＋ Atom.to_string

```diff_elixir
iex> for {k, v} <- user_a, into: %{}, do: {Atom.to_string(k), v}
%{"id" => :id000, "name" => "hoge", "weight" => 49}
```

## Jason.encode! ＋ Jason.decode!　※ただし要注意

アトムのバリューが、文字列に変化してしまうので注意

```diff_elixir
iex> user_a |> Jason.encode! |> Jason.decode!
%{"id" => "id000", "name" => "hoge", "weight" => 49}
```
webpackでバンドルしてブックマークレットを作ってみた

## はじめに

ブックマークレットを2回クリックするのを1回のクリックにしようと思って、2つのブックマークレットのファイルを1つのファイルにしました。そうしたら「保守性が下がった」と思いました。なぜなら異なる機能で別々のファイルに分かれていた関数が1つのファイルに入ったからです。その対策としてwebpackでバンドルすることで別々のファイルから1つのブックマークレットを作る方法を調べて作ってみました。

## 本記事の対象者

- webpackを使って複数ファイルをバンドルして1つのブックマークレットを作る方法を知りたい方。
- ブックマークレットの規模が大きくなった方。

## 調べたURL

webpackの公式ウェブサイトを読みました。次のURLが役に立ちました。

| タイトル         | URL                                                 |
| ---------------- | --------------------------------------------------- |
| Concepts         | https://webpack.js.org/concepts/                    |
| Getting Started  | https://webpack.js.org/guides/getting-started/      |
| Writing a Plugin | https://webpack.js.org/contribute/writing-a-plugin/ |
| Plugin API       | https://webpack.js.org/api/plugins/                 |
| Node Interface   | https://webpack.js.org/api/node/                    |

## どうやって作るか

webpackの出力ファイルはブックマークレットに必要な「javascript:」のラベルが先頭に付いていません。これを付ける必要があります。

調べたところ、ラベルを付けるには2つの方法がありそうです。

1つめの方法はプラグインのhookを使うことです。Plugin APIのページにある約135個のhookのなかでassetEmittedのhookを選びました。このhookはファイル名やファイルの中身が得られます。

次のプログラムはPlugin APIのページ（Compiler Hooks）にあるサンプルプログラムです。

```javascript
compiler.hooks.assetEmitted.tap(
  'MyPlugin',
  (file, { content, source, outputPath, compilation, targetPath }) => {
    console.log(content); // <Buffer 66 6f 6f 62 61 72>
  }
);
```

webpackがファイル出力したタイミングで先頭に「javascript:」のラベルをつけてファイルを上書きします。

2つめの方法はノードインタフェースを使うことです。

次のプログラムはNode Interfaceのページにあるサンプルプログラムです。

```javascript
const webpack = require('webpack');

const compiler = webpack({
  // ...
});

compiler.run((err, stats) => {
  // ...

  compiler.close((closeErr) => {
    // ...
  });
});
```

このNode.jsのサンプルプログラムはwebpackを実行します。webpackを実行した後で出力されたファイルの先頭に「javascript:」のラベルつけてファイルを上書きします。

## GitHubで公開

調べて作った参照用のプログラムを次のURLで読めます。

https://github.com/querykuma/MakeBookmarklet

## さいごに

webpackのプラグインを使う方法とノードインタフェースを使う方法の2つの方法で作ってみました。

`npx webpack watch` のコマンドを使えばファイルの変更を常に監視して出力ファイルに反映できるので、プラグインのhookを使う方法の方がおすすめです。
PDF連動型ずんだもんナレーター

# PDFページに連動したVOICEVOXナレーター
このプログラムは、PDFを読み取りその内容を表示しながら、VOICEVOXでプログラム中の原稿を読上げます。

## 動作環境
WindowsでもLinuxでもVOICEVOXが起動していれば動作すると思います。
動作チェックはLinuxでしかやっていません。

## 必要なライブラリ
PySimpleGUI、pdf2image、requests、pyaudio

## code
コードはご自由に変更してお使いくださいませ。
~~~python
#!/usr/bin/python3
# Programed By M.kawase embed-ai labo. LTD
import PySimpleGUI as sw
import pdf2image as p2i
import requests as req
import json
import pyaudio as pa

wdef = [[sw.Image(key="IM01")]]
imgs=p2i.convert_from_path('./Linux01.pdf',80,fmt='png')
#                File Path  ^-----------^  ^^ 大きさ
#　ここにナレーションを入れます。('ナレーション',キャラ番号)の順で入れます。
mess = [
    ('読上げテスト１',3),
    ('読上げテスト２',3),
    ('読上げテスト３',3),
    ('',0)
]
dispnum=0

# sperk function
def speak(mess,no):
    qu_requrl='http://localhost:50021/audio_query'
    ad_requrl='http://localhost:50021/synthesis'
    reqprm = (('text',mess), ('speaker',no), )
    rsvdat = req.post(qu_requrl, params=reqprm)
    wavdat = req.post(ad_requrl,
        headers={"Content-Type": "application/json"},
        params = reqprm,
        data = json.dumps(rsvdat.json())
    )
    wav = wavdat.content
    dev = pa.PyAudio()
    dev_stream = dev.open(format=pa.paInt16,
        channels=1,rate=24000,output=True)
    dev_stream.write(wav)
    dev_stream.close()
    dev.terminate()

win = sw.Window('vvpdf',wdef,size=(600,400))
for img in imgs:
    img.save('pdfimg.png','PNG')
    win.finalize()
    win['IM01'].Update(filename='pdfimg.png')
    e,v=win.read(timeout=1000,timeout_key="T01")
    speak(mess[dispnum][0],mess[dispnum][1])
    dispnum += 1

win.close()
~~~

## 解説動画
このプログラムを使った改修点の解説動画を上げてあります。

https://youtu.be/IptS8nSvYKo

## スピーカー番号を調べる方法
ずんだもん以外の声を使う場合は、番号を変える必要がありその番号を調べる方法です。

https://youtu.be/ZVfZ3k4RZek

キャラによりライセンス表記が異なりますので各キャラクタでご確認ください。
flutterの数値型の話

rest apiで取得したdouble?型のフィールドにnullが入ることがあり、調べたら結構面倒くさい事になっていた。

確認するとサーバー側は、nullではない値を返している、しかし受け取るとnullになる。

はて？

正しく取得できているデータを眺めていると、全て小数点以下の値がある値だった。
もしかして、型変換に失敗してnullになっているのかも？

更に確認をする。
恐らく、openapi-generatorで出力したパーサーが雑なのが問題だと思われるが結構嫌な感じです。
正直、double型のフィールドに関しては、1.0だろうと1だろうと同値になるのであれば値として処理してほしかった。

## number型のformatを指定する場合
```openapi.yaml
    data_value:
      type: number
      format: float
```

```model.dart
  double? data_value;
```

 1 => null
 1.0 => 1.0


## number型のformatをしない場合
```openapi.yaml
    data_value:
      type: number
```

```model.dart
  num? data_value;
```
 1 => 1
 1.0 => 1.0


## 結果

結局、時間も無いのでサーバー側でdouble型(小数点付けた値)で送ってるように変更を頼みにくいので受け取り側のフィールドをnumで受けるように修正しました。
intでもdoubleでもどちらでも良いnumという微妙な型だと思っていましたが、時間が無い時には助かります。
時間があるときに、この辺りの型の問題は綺麗にしたいと思います。

正直、pythonもそうだけど、dartもデータのデコード関連の作りは物凄い微妙な感じです。
C#の様なジェネリックを使っていい感じにできると非常にすっきりするのですが難しいですね。
ABC050 ARC066 の問題を解いてみました


## A問題
https://atcoder.jp/contests/abc050/tasks/abc050_a


if文で足し算か引き算かを判断して、結果を出力します。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  int a, b;
  char op;
  cin >> a >> op >> b;
  
  if(op == '+'){ //足し算なら
    cout << a + b << endl;
  }
  else{ //引き算なら
    cout << a - b << endl;
  }
}
~~~

## B問題
https://atcoder.jp/contests/abc050/tasks/abc050_b

飲むドリンクを全探索しましょう。
具体的には、選んだドリンクが効果する問題の 解く時間を変えて、
全ての時間を解くのにかかる時間を計算しましょう。

~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.

int main(void){
  int n;
  cin >> n;
  int t[n];
  for(int i = 0; i < n; i++) cin >> t[i];
  int m;
  cin >> m;
  int p[m], x[m];
  for(int i = 0; i < m; i++){
    cin >> p[i] >> x[i];
    p[i]--;
  }
  
  for(int i = 0; i < m; i++){ // それぞれのドリンクを試す
    int timesum = 0;
    for(int j = 0; j < n; j++){ // 実際にシミュレーション
      if(j == p[i]){ //ドリンクの効果がある問題なら
        timesum += x[i];
      }
      else{
        timesum += t[j];
      }
    }
    cout << timesum << endl;
  }
}
~~~



## C問題
https://atcoder.jp/contests/abc050/tasks/arc066_a


まずは、$N$ が偶数の時の場合について考えます。
自分の左に並んでいた人数と自分の右に並んでいた人数の差の絶対値 の並びは、
$N-1,N-3,...,3,1,1,3,...,N-3,N-1$ となるはずです。
なので、上のような並びに並び替えられない場合は、答えは 0 になります。

次に、$N$ が奇数の時の場合について考えます。
自分の左に並んでいた人数と自分の右に並んでいた人数の差の絶対値 の並びは、
$N-1,N-3,...,2,0,2,...,N-3,N-1$ となるはずです。
なので、上のような並びに並び替えられない場合は、答えは 0 になります。

そして、この問題は 元の並び方が何通りあるかを求める問題です。
並び替える方法には、同じ種類の数の前後を入れ替えるという方法があります。
$[N \div 2]$ 個 の種類の並び替えができるので、元の並び方の組み合わせは、$2^{N/2}$ と表せます。



~~~C++
#include <bits/stdc++.h>
using namespace std;
//Created by karaju.
const long long MOD = 1000000007;

int main(void){
  int n;
  cin >> n;
  int x[n]; //絶対値がiである人の人数 = x[i]
  for(int i = 0; i < n; i++) x[i] = 0;
  bool ok = true;
  for(int i = 0; i < n; i++){
    int a;
    cin >> a;
    // a が条件を満たしているかを確かめる
    if(n % 2 == 1){ // n が奇数なら
    
      if(a % 2 == 0){  // a が偶数なら
        //0が2つあることはありえない
        if(a == 0 && x[a] >= 1) ok = false;
        //それ以外の数も3つ以上あることはありえない
        else if(x[a] >= 2) ok = false;
        x[a]++;
      }
      else ok = false;
      
    }
    else{ // n が偶数なら
      if(a % 1 == 0){ // a が奇数なら
      //同じ数が3つ以上あることはありえない
        if(x[a] >= 2) ok = false;
        x[a]++;
      }
      else ok = false;
    }
  }
  
  if(!ok){  //条件を満たしていなかったなら
    cout << 0 << endl;
    return 0;
  }
  
  long long ans = 1;
  for(int i = 0; i < n / 2; i++){ // 2^(n/2) を計算する
    ans *= 2;
    ans %= MOD;
  }
  cout << ans << endl;
}
~~~




## D問題
https://atcoder.jp/contests/abc050/tasks/arc066_b

あとで





[^1]: この記号は切り捨てを表しています。