OmniAICreator/Qiita-1.07M huggingface dataset:
Blobライフサイクル管理で自動削除された履歴をログに残す

この記事は [セゾン情報システムズ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sisco) ページ2の11日目の記事です。

Azure Blob Storageにはライフサイクル管理という機能があります。
これは例えば90日間変更がないBlobを自動的に削除したり、ホット層からクール層に自動的に移動したりすることができます。

今回このライフサイクル管理で自動削除されたBlobを、ログとして記録することができるのかを確認しました。

# ライフサイクル管理
* Azure Portalから[ライフサイクル管理]→[ルールの追加]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/d8a0febb-7d04-8c5e-00d8-8ee8ad5fe23d.png)

* ストレージアカウントの全てのBlobを対象にすることもできるし、特定のコンテナーのみに絞ったりもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/4865b71a-6bd8-fb96-6055-f44c017397b2.png)

* 例えば最終変更日が90日以上前のものは削除するといったルール設定が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/aee17119-ae16-11a2-7d51-19d119538e12.png)

# 診断設定
* 診断設定を使うことで、Blobの削除操作をログに記録することができます。
* Azure Portalから[診断設定]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/bc90fbec-5e41-2945-85ca-cd18c19439fa.png)

* [StorageDelete]を保存します。保存先はLog Analyticsやストレージアカウントが選べますが、今回はストレージアカウントに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/d1d56f71-9a19-8592-d97d-1b54626987ad.png)

# ログ確認
* 実際にライフサイクル管理で削除された場合、以下のように記録されていることが確認できました。

```
{
    "time": "2022-12-10T11:26:22.8742962Z",
    "resourceId": "/subscriptions/[SubscriptionId]/resourceGroups/[ResourceGroupName]/providers/Microsoft.Storage/storageAccounts/[StorageAccountName]/blobServices/default",
    "category": "StorageDelete",
    "operationName": "DeleteBlob",
    "operationVersion": "2020-02-10",
    "schemaVersion": "1.0",
    "statusCode": 202,
    "statusText": "Success",
    "durationMs": 9,
    "callerIpAddress": "x.x.x.x:50740",
    "correlationId": "xxx",
    "identity": {
        "type": "SAS",
        "tokenHash": "xxx"
    },
    "location": "Japan East",
    "properties": {
        "accountName": "[StorageAccountName]",
        "userAgentHeader": "xAzure/1.0 AzureStorage/1.0 ObjectLifeCycleScanner/0.50",
        "clientRequestId": "xxx",
        "serviceType": "blob",
        "objectKey": "/[StorageAccountName]/test/test.txt",
        "metricResponseType": "Success",
        "serverLatencyMs": 9,
        "requestHeaderSize": 645,
        "responseHeaderSize": 300,
        "tlsVersion": "TLS 1.2",
        "accessTier": "None"
    },
    "uri": "xxx",
    "protocol": "HTTPS",
    "resourceType": "Microsoft.Storage/storageAccounts/blobServices"
}
```

* 次に気になるのが、手動削除した場合とライフサイクル管理で自動削除された場合で区別することができるのかです。ログを見比べたところ以下の違いがありました。

```json:ライフサイクル管理
"userAgentHeader": "xAzure/1.0 AzureStorage/1.0 ObjectLifeCycleScanner/0.50",
```

```json:手動削除
"userAgentHeader": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
```

* ライフサイクル管理と手動削除では[userAgentHeader]の値に違いがありました。これをチェックすることで自動削除されたか確認ができそうです。

以上
Twitterに生えてる草を焼き払えるChrome拡張

[クソアプリアドベントカレンダー2022](https://qiita.com/advent-calendar/2022/kuso-app)の12日目の記事です。
Twitterに生え散らかっている草を焼き払えるChrome拡張を作りました。
![e856fea28a883104522bac7e245d849f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265114/d9a050c3-7262-a94d-ef58-a8e3ce16ea1d.gif)
こんな感じで焼き払えます。

## 使ってみたい！という方

こちらにコードと使い方を載せています。

https://github.com/mega-yadoran/burning-kusa

## 解説

メインの仕組みは単純で、 "草" をクリックしたときにGIF画像を表示しているだけです。

全体の流れは、
1. bodyへのnodeの追加を監視する
2. 追加されたnodeの中のspanタグを取得する
3. spanタグの中に "草" という文字が含まれている場合、"草" の部分にクリックイベントを追加
4. "草" をクリックしたときに、GIF画像を表示する
5. "草" を "灰" に書き換える

という感じです。

要素をいくつかピックアップして具体的に解説していきます。

### nodeの追加を監視

Twitterはツイートのデータを非同期で取得して表示しています。  
なので、 "草" という文字列を探すのは、ツイートが読み込まれた後でなければいけません。

それを実現するためにbodyにnodeが追加されたことを[MutationObserver](https://developer.mozilla.org/ja/docs/Web/API/MutationObserver)を使って監視しています。

```javascript
// bodyに新しいnodeが追加されたときにonNodeAddedを発火する
const observer = new MutationObserver(onNodeAdded);
observer.observe(document.body, {
  childList: true,
  subtree: true,
});
```

`MutationObserver` は変更を検知したときにcallbackに対して `MutationList` というListを渡します。
この `MutationList` の扱いが少々ややこしいのですが、ここでは割愛します。調べるといろいろ出てくると思います。

### spanタグの中の "草" の部分にだけクリックイベントを追加

spanタグ内に含まれる"草"の文字をspanタグで置換しています。

```javascript
span.innerHTML = span.innerHTML.replaceAll(
  "草",
  '<span class="burn-target">草</span>'
);
```

これを実行すると、たとえば元々のDOMが

```HTML
<span>これは草だわ</span>
```

となっていた場合、以下のように入れ子になります

```html
<span>これは<span class="burn-target">草</span>だわ</span>
```

これで "草" の部分だけ `burn-target` というclassを付与できました。  
あとはこのclassに対してクリックイベントを追加して、GIFを表示する処理を呼ぶだけです。

### "草" をクリックしたときにGIF画像を表示する

```javascript
kusaSpan.addEventListener("click", (event) => {
  // クリックした位置を基準に表示位置を設定する
  const imagePosition = {
    x: event.clientX + window.pageXOffset,
    y: event.clientY + window.pageYOffset,
  };
  // GIFを表示する
  const image = document.createElement("img");
  image.src = chrome.runtime.getURL("kaiju.gif") + "?" + Date.now();
  image.style.position = "absolute";
  image.style.left = imagePosition.x + "px";
  image.style.top = imagePosition.y + "px";
  document.body.appendChild(image);
});
```

クリックした位置を基準にしてGIFを表示しています。

ポイントはここです。

```javascript
image.src = chrome.runtime.getURL("kaiju.gif") + "?" + Date.now();
```

`chrome.runtime.getURL()`というのがChrome拡張におけるリソースを呼び出すメソッドです。

そして、末尾にタイムスタンプのクエリをつけています。
 `image.src = chrome.runtime.getURL("kaiju.gif")` のように単純にGIFを読み込むだけだと、GIFがブラウザにキャッシュされてしまいます。  
キャッシュされた場合、GIFを1度表示したあとに再度表示すると前回の続きから再生されてしまいます。
これだと "草" をクリックしても2度目以降は最初からGIFが再生されません。
そこでタイムスタンプのクエリをつけることでキャッシュされるのを防ぎ、GIFが常に最初から再生されるようにしています。

## ソースコード

もう一度載せておきます。
お好きに改変してお使いください。

https://github.com/mega-yadoran/burning-kusa

Chrome拡張は気軽にお遊びツールを作れるのでとてもいいですね。

## 参考

- [MutationObserver - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/MutationObserver)
-  [GIFアニメーションを任意のタイミングで動かす | cly7796.net](https://cly7796.net/blog/javascript/move-gif-animation-at-arbitrary-timing/)
text-align と justify-content について

# text-align:center; と justify-content:center;
cssを記述する際、要素を中央寄せにしたいとき、この二つのどっちを使えばいいのか、毎回わからなくなる。なので整理してみる。
# text-align
```
text-align CSS プロパティは、
ブロック要素または表のセルボックス内におけるインラインレベルコンテンツの水平方向の配置を設定します。
これは vertical-align と同じように機能しますが、水平方向に機能することを意味します。
```

# justify-content
    CSS の justify-content プロパティは、
    フレックスコンテナーの主軸およびグリッドコンテナーのインライン軸に沿って、
    中身のアイテムの間や周囲に間隔を配置する方法を定義します。

# まとめ
text-alignであれば要素を中央寄せができて、justify-contentであればフレックス要素の中身の要素を中央よせ（つまりフレックス指定されている親要素に対する中央寄せ）ができる。

##  補足　vertical-align についてなど
    vertical-align は CSS のプロパティで、
    インラインボックス、インラインブロック、表セルボックスの垂直方向の配置を設定します。

    vertical-align はインライン要素、インラインブロック要素、
    表のセル要素だけに適用されることに注意してください。
    つまり、ブロックレベル要素の垂直方向の配置には使用できません。
高さを調整できるvertical-alignは、divなどのブロック要素には使えないということです。

<br>
htmlとcss、だいぶ扱えるようにはなってきたものの、理論的・意味的な部分がおざなりのままでした。今回のように、一呼吸おいて改めて調べてみることは大切ですね。

## 参考
https://developer.mozilla.org/ja/docs/Web/CSS/text-align
https://developer.mozilla.org/ja/docs/Web/CSS/vertical-alignhttps://developer.mozilla.org/ja/docs/Web/CSS/justify-content
nginx on docker

久々にdockerでnginxを動かそうと思った。

４年ぶりかもしれない。

```macOS:basl
$ docker run -it nginx /bin/bash
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
025c56f98b67: Pull complete 
ca9c7f45d396: Pull complete 
ed6bd111fc08: Pull complete 
e25b13a5f70d: Pull complete 
9bbabac55ab6: Pull complete 
e5c9ba265ded: Pull complete 
Digest: sha256:ab589a3c466e347b1c0573be23356676df90cd7ce2dbf6ec332a5f0a8b5e59db
Status: Downloaded newer image for nginx:latest
```

ファイル共有、ポート設定などをしていない。

詳細の作業は明日以降。ごめんなさい。


<この項は書きかけです。順次追記します。>
# 参考資料

Dockerでnginx

https://qiita.com/meidaimae/items/a982f4337cf7e44bef3b

CentOS8にNginxを入れずにdockerでNginx起動

https://qiita.com/ebios/items/837517de4c93c7210c87

nginxの導入

https://qiita.com/soushiy/items/8d1b8ed618e086af2237

DockerでNGINX + NGINX Unit + MySQLの環境を構築

https://qiita.com/t_okkan/items/f4baba5ee29216522e08

Docker For Windowsでdocker hubのnginxイメージを使用してコンテナを作成してみた。

https://qiita.com/shinjimorimoto/items/988d36486bb920d6a790

# Countdown Calendar 2022

今年企画した6つのCountdown Calendarと、それぞれの記事一つをご紹介します。

AUTOSAR Countdown Calendar 2022

https://qiita.com/advent-calendar/2022/autosar

AUTOSAR References to ISO, IEC, ITU, IEEE, RFC and SEA etc.

https://qiita.com/kaizen_nagoya/items/d7d252211e10a79516df

Automotive Handbook Countdown Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

Basic principles, ボッシュ自動車handbook(英語)11版まとめ<2>

https://qiita.com/kaizen_nagoya/items/24a1ba5da3d09b2a95d1


2022 いいねをいただいた記事ランキング(O.K.版) Countdown Calendar 2022

https://qiita.com/advent-calendar/2022/goods

2022年１月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/0ee589a8edaeab24fd2a

AdCale(O.K.) Countdown Calendar 2022

https://qiita.com/advent-calendar/2022/adventcalendar2022

「会議は15分未満」に。小耳にはさんだ話。

https://qiita.com/kaizen_nagoya/items/510c47c5d1e8d03145db

ABC language (O.K.版） Advent Calendar 2022

https://qiita.com/advent-calendar/2022/abc_ok

LLVMソースコードのコンパイルをしようと思ってハマった罠とそこから脱出するための努力

https://qiita.com/kaizen_nagoya/items/16f270e42b947756ced3

ABC maker(O.K版） Advent Calendar 2022

https://qiita.com/advent-calendar/2022/abcmaker

JAXA/IPA クリティカルソフトウェアワークショップ WOCS言語関連発表(改定版)

https://qiita.com/kaizen_nagoya/items/4789832baf494cb74626

CountdownCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b

誤差の評価が苦手（専門分野以外）

https://qiita.com/kaizen_nagoya/items/cc3a50827b24ab80985f




 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 20221229
ver. 0.02 URL追記　20221231
【PostgreSQL】連結リストを先頭から順に表示する

DB に連結リストを実装する機会があったのですが、先頭から順に表示するのが予想に反して辛かったので実装例を作っておくことにしました。

:::note info
PostgreSQL v9.4 で動作を確認しました。
:::

### 計算量

:::note warn
レコード数 $n$ に対して $\mathcal{O}(n\log{n})$ 程度の時間計算量で動作する気がしていますが、[再帰的問い合わせの評価を確認すると](https://www.postgresql.jp/document/9.6/html/queries-with.html) $\mathcal{O}(n^2)$ っぽい……？
:::

今回紹介するコードは単純かつ連結な有向グラフとして連結リストを DB 上に実装しています。

<details><summary>？</summary>

順序付けはアプリケーションに丸投げすれば簡単に $\mathcal{O}(n)$ を達成できます。記事書くのやめていいですか？
</details>

# テーブル定義とお試しデータ
```sql
CREATE TABLE items (
  id INT PRIMARY KEY,
  label TEXT,
  next_id INT
);
CREATE INDEX items_index ON items (id);

INSERT INTO items (id, label, next_id) VALUES (1, 'a', 3);
INSERT INTO items (id, label, next_id) VALUES (2, 'd', NULL);
INSERT INTO items (id, label, next_id) VALUES (3, 'b', 4);
INSERT INTO items (id, label, next_id) VALUES (4, 'c', 2);
```

片方向連結リストを表現している `items` テーブルを定義し、そこにいくつかのデータを流し込みます。
`id` を主キーとし、`id` が `next_id` であるようなレコードへ向かって辺を張っているような構造です。`label` は連結リストにおいて必須のカラムではありません。

INSERT まで実行するとテーブルは次のようになります。

|id  |label  |next_id  |
|---|---|---|
|1  |'a'  |3  |
|2  |'d'  |NULL  |
|3  |'b'  |4  |
|4  |'c'  |2  |

# クエリ
連結リストを先頭からの順序で表示するクエリです。

```sql
-- 先頭のノードは与えられていることにする
-- 双方向連結リストならただ前方向に探索すれば先頭を見つけることができる

WITH RECURSIVE dfs_linked_list(
  id,
  label,
  next_id,
  depth
) AS (
    SELECT id, label, next_id, 0 AS depth
    FROM items
    WHERE id = 1
  UNION ALL
    SELECT t1.id, t1.label, t1.next_id, t2.depth + 1
    FROM items t1, dfs_linked_list t2
    WHERE t2.next_id IS NOT NULL AND t1.id = t2.next_id
)
SELECT 
  id,
  label,
  next_id
FROM dfs_linked_list
ORDER BY depth;
```

WITH RECURSIVE を使った再帰問い合わせで `depth` というパラメータを管理します。これは連結リストに対する深さ優先探索において、そのノードの深さを表します。そしてそれはそのまま表示順に対応しますから、`depth` を使ってソートしてあげれば先頭からの順序で出力されます。

|id  |label  |next_id  |
|---|---|---|
|1  |'a'  |3  |
|3  |'b'  |4  |
|4  |'c'  |2  |
|2  |'d'  |NULL  |

実行結果は上記の表のようになります。

# おわり
単純に FUNCTION を使った再帰だとネストできる深さに制限があってこちらはこちらで扱い辛さがあります。
SQL、順序を扱うの厳しすぎませんか？
collaboflow.補完計画


この記事は [コラボフロー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/collaboflow) の12日目の記事です。

https://qiita.com/advent-calendar/2022/collaboflow

アカウント名は、[好きなドラマ](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%B3%E3%82%BF%E3%83%AA%E3%82%B9%E3%83%88_(%E3%83%86%E3%83%AC%E3%83%93%E3%83%89%E3%83%A9%E3%83%9E))のシリアルキラーから拝借しました。
よかったら冬休みにでも、見てみてくださいね😇


## 🏃‍♂️補完から「逃げちゃダメだ！」

コラボフローでは ***[コラボフロー JavaScript API](https://collaboflow.zendesk.com/hc/ja/sections/360000040276)*** を利用することで、
申請書の入力や操作を補助するためのカスタマイズができます。

カスタマイズのコードを書く時、`collablow.`と入力したら、
続くコードが **補完**（**インテリセンス**）されたらなぁ…🙄って思うことありませんか？？？？？

***[リファレンス](https://collaboflow.zendesk.com/hc/ja/sections/360000040276)*** 見て確認してコーディングでも、もちろんいいのです。
でも、プログラマなら３大美徳の一つ、***怠惰*** が発動しますよね。

なーのーでー！

書きましたよ。
独自の型定義ってやつをね！！

## 🧪型定義ファイルとカスタマイズコードの試作零号機

型定義ファイルとサンプルは、こちらからどうぞ🧑‍🎄

:::note warn
REST APIの型定義をconditional typeで切り替える！ができてないのと、
そもそもかなーり雰囲気で書いてます…😶‍🌫️
:::

https://github.com/mstkk1110/collaboflow-js-dts


## 🔫目標（collaboflow）にドット（.）を入れて補完

試しにサポートサイトの ***[カスタマイズサンプル](https://collaboflow.zendesk.com/hc/ja/articles/360000321936)*** を補完アリで書いてみると、こんな感じ

全ての`collaboflow.`にありがとう🛐

![intelicense.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952882/53c2d9e7-aba5-b04e-db52-ab96e34b42ca.gif)


## 😄補完すればいいと思うよ

補完のある世界へようこそ
簡単にコード書けるのは大正義🥳

カスタマイズする際のお役に立てれば幸いです🙏

いっじょう～

### 参考情報

* [definition-file-theory-a-deep-dive - microsoft/TypeScript-Handbook](https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/declaration%20files/Deep%20Dive.md#definition-file-theory-a-deep-dive)
* [碇シンジさんの名言](https://www.google.com/search?q=%E7%A2%87%E3%82%B7%E3%83%B3%E3%82%B8+%E5%90%8D%E8%A8%80)

---

13日目は、@kenny_engineer さんです！
お楽しみに😘
LovyanGFX で画面描画(1):Hello World

12/17(土) 開催の「低レベル勉強会2022年12月」
https://lowleveltokyo.connpass.com/event/269268/
後半のテキスト(1/3)です。

Arduino などが LCD などで画面描画するときにはグラフィックライブラリを使うと便利です。
定番のグラフィックライブラリでは多くのLCD/OLED/LEDマトリックスのコントローラICのコマンドや、配線が抽象化されて細かな違いを問題にせずに画面のドット数、接続方法などをせっていするだけで画面に描画ができるようになります。
画面の描画だけではなく、フォントの扱いやグラフィックスイメージなども扱えるようになっていて、自前でアレコレするのに比べかなり便利になっています。


グラフィックライブラリのうち、LovyanGFX を使うときは ESP32 などの デバイスを使うことになるのですが、画面のデザインは手間がかかります。

- デザイン 
- プログラム 
- ビルド
- デバイスに転送
- デザイン確認

 のループを回さないといけないのですが結構ビルドにばかにならない時間がかかったりしてしまいます。この間は1秒でも早いほうがいいですね。

今回は LovyanGFX の基本的なところを PC 上で試し、初期のループを早く回してなれていくことにします。

# 環境構築

Windows の方はこちら

「LovyanGFX for Windowsを使ってみた」
https://qiita.com/pokibon/items/4f6f9b1f733ad60c708a

Linux (と多分 Mac も同じハズ) の方はこちら
「LovyanGFX for PC を Ubuntu Linux で試す」
https://qiita.com/nanbuwks/items/5ec1bf2c3c074f0b3a05



# Hello World!

Arduino 環境と同じように書いていきます。

setup() と loop() 関数があり、 setup() は最初に一度だけ呼ばれます。 loop() は setup() 実行後に呼び出され、繰り返します。

```

#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp>

LGFX display ( 64, 32 );

void setup()
{
  display.init();
}

void loop()
{
  display.setCursor(0,0);
  display.setFont(&fonts::Font0);
  display.setTextColor(TFT_WHITE, TFT_BLACK);
  display.setTextSize(1);
  display.print("Hello LovyanGFX World!");
} 
        
```

これを実行してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/48fda0d5-bc25-dd76-a2d8-e648cc3fd036.png)


ちっちゃ!

# 画面を大きくしてみる

```
LGFX display ( 128, 64 );
```
のように、数字を大きくしたら画面が大きくなります。

しかしながら後々実デバイスに移行して試すつもりなので、手元に実デバイスがある方はその画面サイズに合わせたいですね。

でも PC でテストしているときには 実デバイスはドット数が少ないので PC では大きく表示したいです。それについては画面拡大が使えます。

```
LGFX display ( 128, 64 ,5 );
```
とすると縦横5倍で画面表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a1d4f94d-3460-2d4f-609b-4117a87fe735.png)


さて、フォントを選ぶことができます。


```
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp>

LGFX display ( 256, 256 ,1 );

void setup()
{
  display.init();
}

void loop()
{
  display.setCursor(0,0);
  display.setTextColor(TFT_WHITE, TFT_BLACK);
  display.setTextSize(1);
  display.setFont(&fonts::Font0);
  display.printf("Font0\n");
  display.setFont(&fonts::Font2);
  display.printf("Font2\n");
  display.setFont(&fonts::Font4);
  display.printf("Font4\n");
  display.setFont(&fonts::Font6);
  display.printf("Font6\n");
  display.setFont(&fonts::Font7);
  display.printf("Font7\n");
  display.setFont(&fonts::Font8);
  display.printf("Font8\n");
}

```
このようにすると、以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/28af4927-fd3f-e297-b788-dbb704d1a871.png)
Font6,7,8は数字だけのフォントだそうです。


もっと多くのフォントの情報はこちら

https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/3_fonts/3_fonts.ino
vPro対応PCを検証用仮想プラットフォームにする話(3)〜標準WebUIによるリモート制御編〜

# vPro対応PCを検証用仮想プラットフォームにする話(3)〜標準WebUIによるリモート制御編〜
## [前回](https://qiita.com/JUNKER_TOMATO/items/89f98e24ba0c442278ad)まで
vPro対応PCのintel ME設定画面から AMT(Active Managment Technology)の設定を行いました。

今回は設定済みのvPro対応PCへのリモート接続方法をご紹介します。

## AMTへのリモート接続方法について
有効にしてIP設定を行ったAMTはリモートから接続できるようになります。<br>

## pingによる疎通確認
動作確認のため、リモート端末側から vPro対応PCのAMTに設定したIPアドレスに ping を打ってみます。
確認のためvPro対応PCを**電源をOFF**にした状態で、AMTに設定したipアドレスに対して ping を打ちます。

```bat
PS C:\Users\user> ping 192.168.0.80

192.168.0.80 に ping を送信しています 32 バイトのデータ:
192.168.0.80 からの応答: バイト数 =32 時間 =3ms TTL=255
192.168.0.80 からの応答: バイト数 =32 時間 =3ms TTL=255
192.168.0.80 からの応答: バイト数 =32 時間 =3ms TTL=255
192.168.0.80 からの応答: バイト数 =32 時間 =3ms TTL=255

192.168.0.80 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 3ms、最大 = 3ms、平均 = 3ms
PS C:\Users\user>
```
疎通できない場合にはintel MEセットアップ画面から、AMTのネットワーク設定を確認してください。<br>
また、vPro対応PCの電源を入れた後(OS等が起動していない状態)に疎通できるようになる場合には、AMT の POWER CONTROL設定が `Desktop: ON in S0` になっている可能性があります。vPro対応PCの電源が落ちている状態でもAMTに接続できるようにするためには、`Desktop: ON in S0, ME Wake in S3,S4-5` に設定してください。
![3-1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/03571390-4e12-697f-9522-0430839f6ae6.jpeg)

## WebUIによる接続とコントロール

pingによるIP疎通が確認できている場合、AMTは `16992/tcp` で httpで待受をしています。
リモート端末側から 以下URLにアクセスしてみてください。<br>

    http://<vPro対応PCのAMTに設定したIPアドレス>:16992/

正常にアクセスできると、以下のような Log On 画面が表示されます。
![3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/72c63c74-880c-596e-e2c7-ccb43b2a8c1a.png)
ユーザ名：admin、設定したパスワードでログインします。<br>
以下のようなWebUIが表示されます。

![3-2b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/6ff2c1f5-ba72-607f-fa17-335f493e506e.png)



AMTの標準WebUIでは以下のことが可能です。
|AMT WebUI上の表示|意味|備考|
|:-:|:-|:-:|
|System Status|システムの状態||
|Hardware Information|ハードウェア情報の表示<br>(マザーボードの型番、BIOSバージョン情報、CPU型番、クロック数,メモリDMM型番,容量、SPEED,DISK型番、容量)||
|Event Log|POSTエラーを含む、ハードウェアイベントを表示||
|Remote Control|電源ON/OF、ハードリセット||
|Power Policies|AMTを本体電源OFF状態で起動するかどうか。|intel MEセットアップ画面の`POWER CONTROLE`設定と等価|
|Network Settings|AMTのIPv4設定<br>|intel MEセットアップ画面の 設定と等価|
|IPv6 Network Settings|AMTのIPv6設定|intel MEセットアップ画面の 設定と等価|
|System Name Settings|AMTのホスト名、ドメイン名の設定|intel MEセットアップ画面の 設定と等価|
|User Accounts|AMTログインユーザ名、パスワード、ロールの設定||
|Web Application Links|WebUIからは設定不可||

AMTの標準WebUIで実質的に使えるリモートからの制御は`Remote Control`の電源コントロールだけになります。
目立たない機能かもしれませんが、これは非常に役に立ちます。

ネットワーク経由の電源ONの仕組みとして`WoL`がありますが、ハードウェア、ファームウェア、OS側の設定を適切に行わないと機能しません。起動のためのマジックパケットがUDPで特殊なツールを必要としますし、マジックパケットはEthernetブロードキャストとして送信されるため、同一L2ブロードキャストドメイン≒同一IPv4サブネット内でしか機能しません。<br>
何よりWoLはパケット送信による電源OFF/ONの成否がすぐに分かりません。

その点、AMTは汎用Webブラウザでアクセスできる＝TCPでアクセスできるため、ルーターの先の別IPv4セグメントからアクセス可能ですし、WebUI上で状態を確認できるため電源ONコマンドを送った結果も把握できます。またハードリセットを含むOSに依存しない強制電源OFFも可能です。

以上の点から、検証用仮装プラットフォームとして使う場合にAMTの`Remote Control`機能は有用です。<br>

## まとめ
今回はAMTの標準WebUIによるvPro対応PCの操作方法をご紹介しました。

## 次回予告
AMTの標準WebUIでは最低限の機能しかできません。

次回はAMT対応ソフトウェアである[MeshCommader](https://www.meshcommander.com/meshcommander)についてご紹介します。
ビルの電源が全落ちした話

謎のアドベントカレンダー、第 13 話です。

## それは入社直後のこと

先輩社員のお手伝いで、客先に出向いて自社サービスの研修を始めたのですが、そもそもサービスに接続できません。

どうしたのだろう？と思っていたところ、会社から先輩社員のもとに連絡があり、

- サービスを提供するためのシステムが置いてあるビルの電源が落ちた
- 電源が落ちた後、シャットダウンに手間取っているうちに UPS のバッテリー残量がなくなり、シャットダウン前に電源が落ちてしまった
- その後ビルの電源は復旧したが、システムが起動しなくなったため SI 業者とともに修復中

とのこと。

結果として研修は中止になりました。

（そしてみんな仲良く徹夜でシステム復旧。我々新人は終電で帰されましたが）

## 原因は

別のフロアで模様替えをしている最中、邪魔な太い線を見つけたので、パワーのある O さんがケーブルカッター（ハンドカッター）で切断したところそれが通電状態の電源ラインだった、とのこと。

（えーと…フロアにあるような電源ラインって見てすぐわかるものじゃないんでしょうか…そしてなぜ普通のオフィスフロアに太い電源ラインが切断できるケーブルカッターがあったんでしょうか…）

当然ショートして、フロアだけではなくビル全体の電源が落ちたようです。

その瞬間、火花が上がったらしいのですが、件の O さんは無傷だったそうです。

（無事でなにより。その後、長い年月を経て O さんはグループ内のとある法人のトップになりました。めでたしめでたし）

それはそれとして、個人的にはもう一つ気になっていたことが。

## UPS、自動シャットダウン連携してなかったんかい！

これ、昔は意外とよくあることだったんですが、せっかく UPS からシリアルケーブルで保護対象のサーバーに接続されていたのに、シリアルケーブルから送られてくる通知信号を受けてシャットダウンできるように設定していなかったようです。

（いまの時代は USB ケーブルかな？）

件のサーバーはこの後対処が行われましたが、ほかに UPS からの出力を「拝借」して別の機器やサーバーを保護しているケースもあったりして、やはり商用電源が落ちたときにシャットダウンできずに死んだり、とか色々ありました。

このあたりは情シス時代には気を付けていたものの、結局ほぼ解消できたのはデータセンターに引っ越してからでした。

ところが！

---

14 日目の記事に続きます。

- **[データセンターなのに電源が全落ちした話](https://qiita.com/hmatsu47/items/fe139be16540bf04abec)**

https://qiita.com/hmatsu47/items/fe139be16540bf04abec
Kotlinで.env読み込み

# Kotlinソース
`.env`をシンプルに読み込む・・・。
```kotlin
class Application {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            File(".env").bufferedReader().readLines().forEach {
                println(it)
                val record = it.split("=")
                System.setProperty(record[0], record[1])
            }
        }
    }
}
```
TypeScript(JavaScript) : 日付加減算は set***() で／ゼロ埋めは "2-digit" で

# 背景
AWS Dynamo DB へデータを入れる際に、以下が必要だった。
自分で実装する道はあるけど・・車輪の再発明なんてしたくないので、公式ドキュメントとかをみてたら、一応みつかったのでその際の備忘録

- テストデータ作成用に、Date().AddHours()
- DynamoDB の Timestamp Sort Key 登録用に、Date/Time を固定長（Zero padding) したい（Date Format)

大切なのは、**簡単に検索結果に飛びつかない**こと

# 結論

## 日付データの加算・減算
データ型の、setHours() 等をそのまま使えばいいだけ。
そう、自分で実装する必要なんてないんです。
とはいえ、AddHours() とかあったほうが分かりやすいし記述も楽なので、その為の再実装はありかな。

例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/1033024a-5138-6116-c6a9-bfce86bc34f4.png)

```typescript: setHours() を使った、Date の加減算
const event = new Date('August 19, 1975 23:15:30');
event.setHours(20);
console.log(`original: ${event.toLocaleString()}`);

event.setHours(event.getHours() + 5);
console.log(`add     : ${event.toLocaleString()}`);

event.setHours(event.getHours() - 3);
console.log(`sub     : ${event.toLocaleString()}`);
```
以下で、ドキュメント見ながら試しましょう

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours

## Date/Time を固定長（Zero padding)
Format を指定してやれば OK

例えば、月の場合は、以下のような options 設定がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/1b6f757b-ed80-b562-8c2b-d8173cc41598.png)

ってことで、基本は "2-digit" に設定してやればいい。
とはいえ、month/day/hour だけかな。
year は 四桁必要だし、minute/second は numeric/2-digit の差が今はなさそう

:::note warn
とはいえ、minute 等を削除すると、表示自体無くなるので、省略は出来ない
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/bcfccc38-b184-5c94-c6fe-c1e3cf8724d2.png)

```typescript: ０埋め処理
const event = new Date(2022,0,2,3,4,5);

console.log(event.toLocaleString());

const options = {
  year: 'numeric', 
  month: '2-digit', 	// numeric: 一桁/ long|short|narrow: "月"
  day: '2-digit',		// numeric: 一桁
  hour: '2-digit', 		// numeric: 一桁
  minute: 'numeric',	// 2-digit: 差はない？ 
  second: 'numeric',	// 2-digit: 差はない？
  timeZone: 'Asia/Tokyo'
}; 
console.log(event.toLocaleString("ja-jp", options));
```
以下で、ドキュメント見ながら試しましょう

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString

### 和暦にしたいとき
```typescript: 和暦
calendar: "japanese", 和暦
```

### 年月日の文字表示だと、ゼロ埋めは、NumberFormat 等で頑張る
dateStyle と year などは並行指定出来ない為、漢字表記の場合には自分でなんとかするしかないのが現状？

:::note warn
メモ: dateStyle は timeStyle と一緒に使用することができますが、他のオプション (weekday, hour, month, など) と一緒に使用することはできません。
:::

```typescript: NumberFormat の例
const number = 3;
console.log(new Intl.NumberFormat('ja-JP', { minimumIntegerDigits: 2 }).format(number));
```

### DateTimeFormat の 詳細
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat

# あとがき
検索するのは大切だけれど、すぐに飛びつくと痛い目を見るので、納得のいくまで調べるのは大切ですね。
勿論、時間制限はあるので、ToDo にしておいて後でってのでも。
CI/CDをよく分かってなかった自分に捧ぐ

# はじめに

- CI/CDってのは「コミットしたときにテストを自動的に走らせること」**ではない**
- システム開発のボトルネック・一番課題になりやすいコードの統合・リリース作業を「小さく」「高頻度で」「自動的に」行うことが市場提供を早めるという話。

# 参考書籍

https://www.amazon.co.jp/dp/B074BQQ96X/

結局はこれを読めという話でしかないけど。
分厚いけど、どれもこれも勉強になるのですごい。
このボリューム全部勉強になるってどういうこと？
自分でQiitaに記事書いて、自分で読み返して、しょうもないなと思うことが何度もあるのに、この文量で全部勉強になるとか何？神？

# 自分の誤解

1. CI/CDツールとして「Jenkins」が紹介されてるのをみる。
1. 「Jenkins」を導入するのがCI/CDだ！みたいなLTをたくさんみる。
1. 自動テスト=CIだと勘違いする

# CI/CDが解決したがっていること

- ソフトウェアのデプロイが手動で毎回リスクが伴う。（もっとも重要でそこでミスったらまずいところなのに、頻度が少ないというだけで、そのリスクを放置している）
- 開発環境・テスト環境・疑似本番環境・本番環境でのデプロイ手順どころか関係者も含め全て異なるため、本番環境でのデプロイは本質的には毎回ぶっつけ本番になっている。
- ちょっとした修正だから本番環境をその場で直した。システムダウンからフォールバックしたらその設定が消えた。

# CI/CDで重要な概念
個人的な抜粋です。

- システムは「小さく」変更すること
- 開発者へのフィードバックを「高頻度」にすること
- 間違ってはいけないものは「自動化」すること

## 小さく変更する

**大きな変更の弊害**
大きく変更する＝ビッグバンマージと表現されるケースもあります。
500のコミット・1000行の変更が含まれたマージリクエストがあったとします。

これをマージした結果、不具合が発生しました。
以前のバージョンでは発生していなかったバグです。

そうなると不具合は500のコミット・1000行の変更のどこかが原因になっています。
他の機能追加も含めてフォールバックになるでしょう。
それによるビジネス的な損失もありますが、開発者としてここからバグを探すのは苦しいでしょう。

**小さな変更の利点**
1のコミット・1行の変更が含まれたマージリクエストだとします。
これで不具合が生じても原因箇所も明確ですし、他の機能も影響しないでしょう。

**具体的なテクニック**
「フィーチャーフラグ」や「抽象的なブランチ」といった戦略があります。
イメージ的には新しい機能は `if false` で囲って実装する感じです。
まぁマジで `if false` で囲うとテストすらできないので、あくまでイメージでしかないですが。

詳しいところは一つのテクニックでも説明大変なのでここでは割愛。

## 高頻度のフィードバック
**年一回のリリースの弊害**
すごく大変でも年一回なら改善しません。
変更を加えてしまった時の影響が大きいからです。
１年分の変更をおじゃんにしてしまう可能性があります。
それなら多少手間でも以前の手順に従うでしょう。

**高頻度のリリースを実現する**
何度もやることになる。しかも影響が小さいのであれば色々とチャレンジすることができるでしょう。
高頻度化は、改善にチャレンジするハードルを下げる効果もあります。

何度もチャレンジできるのであればその分改善も進みます。
開発者がチャレンジしやすくさせ、フィードバックを受けやすくするためには高頻度化は良いアプローチだと思います。

**具体的なテクニック**
概念的なものはいくつか冒頭の書籍でも紹介されていますが、リリース作業などは現場によっても大きく手順が違うと思うので、それぞれの現場で見つけるしかない。。。

そもそも多くの現場ではリリース作業というのは負荷が高いと思います。
自動化を行うことで負荷を下げていく話はあるんですが、最初は大して負荷下がらないと思います。

最初の一歩は諦めることです。
「効率よくリリースしよう」なんてことは諦める。
無駄に何度もリリースしましょう。
そうやって改善するしかない。

上司を説得できない？
冒頭の本を渡しましょう。
読め。話はそれからだ。

## 自動化する
**手動リリースの弊害**
障害の一時対応として入れた変更が、開発環境やテスト環境に入ってなくて新たな障害を呼び起こすことはよく聞く。
なんならそのままにしてたのを忘れてて、本番壊れてバックアップからリストアしたら、設定がなくなって古の障害が呼び覚まされるとか。
割と簡単に想像はできる。でもスピード優先でやる現場は何度も経験してきた。

**自動化へのロードマップ**

1. どの環境のリリースも手順を同じにする。（環境差異は環境変数でカバーしたい）
1. どんな資材のリリースも手順を同じにする。（資材によって違う部分は自動化して隠蔽していく）
1. 人じゃなくていいところは自動化していく。
1. リリース後の検証も自動化していく。

そんな感じ。

# まとめ

- 「CIはコミットしたときにテストが走ること、CDはコミット同時にリリースされること」という理解は浅すぎるぞ自分。
- 大事なのは「小さい」「高頻度」「自動化」がキーワードだ。
- お前の現場に合うCI/CDの形はお前が見つけるしかない。がんばれ自分。

# 次回予告

https://qiita.com/advent-calendar/2022/jutakuagile

本記事は、2022アドベントカレンダー「受託アジャイル」の記事です！他にも興味あれば見てってください。
次回は、TDD導入の四苦八苦です。
Alpine.jsのライフサイクル

# Alpine.jsのライフサイクルは少ない
### ①初期化（x-init）
x-initを使えば、読み込み時に最初に行う処理を定義することができます。
```js
<button x-init="console.log('Im initing')">
```
ただし、以下のコードでは注意が必要です。
x-initは最初に設定した値を上書きするので、下記のコードではx-dataのcounter: 0はx-initで上書きされます。
```js
<div x-data="{counter: 0}">
    <button @click="counter++">ボタン</button>
    <div x-text="counter"></div>
</div>
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="yLEWLeB" data-user="gorimatyan" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/gorimatyan/pen/yLEWLeB">
  Untitled</a> by gorimatyan (<a href="https://codepen.io/gorimatyan">@gorimatyan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

　↑ x-initでcounterが10になっている

### ②プロパティの監視（x-effect）
これはReactのuseEffectみたいなやつです。
x-effect内で定義した関数の中に使われているプロパティに変更があるたびに実行されます。
```js
<div x-data="{ open: false }" x-effect="console.log(open)">
```
この場合はopenプロパティに変更があるたびにx-effectの中のconsole.log(open)が実行されます。

### ③プロパティの監視（$watch）
x-effectとは違って、監視する変数を指定できます。

```js
<div x-data="{ open: false }" x-init="$watch('open', value => console.log(value))">
```
この場合はopenプロパティに変更があるたびにconsole.log(open)が実行されます。

::: note
$watchは更新前の値も取得できる。
```js
<div x-data="{ open: false }" 
     x-init="$watch(
        'open', 
        (value, oldValue) => console.log(value, oldValue))
">               　↑これが変更前の値

    <button @click="open = ! open">Toggle Open</button>
</div>

```
 $watchのコールバック関数の中の第二引数（oldValue）を定義すれば、更新前の値を取得することができる。
:::

# まとめ
とりあえずこの3つ押さえとけば何でも作れる（たぶん）
COLMAP model_aligner

「instantNeRFで遊ぶ Advent Calendar 2022」の15日目です。

今日は「カメラの位置はRealityCaptureの結果を流用」する方法としてCOLMAPのmodel_alignerを使いました。

前半はCOLMAPのmodel_alignerを使った方法、後半は改善した結果を書きました。

:::note
業務外の個人的な検討活動です。
間違っていても責任はとれません。
:::

#### テストデータ
sketchfabのNefertiti statueを使用させていただきました。ありがとうございます。

https://sketchfab.com/3d-models/nefertiti-statue-d148f771c3f44225b56cb7ce8d3c5ce6

#### COLMAP model_aligner
ヘルプでオプションを見ることができました。
![15-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/6d128301-abf2-acaa-e442-0c1c3bb7d549.png)

今回試した入力はこちらです。
> colmap model_aligner --input_path {変換前のモデルデータのフォルダ} 
--output_path {変換後のモデルデータを置くフォルダ } 
  --ref_images_path {変換するカメラ座標を書いたテキストファイル}
  --ref_is_gps 0 --robust_alignment_max_error 1.0

#### 画像群をつくったblenderの画面
上にモデルがあります。
![15-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/d2c8a0bd-8fbe-37ff-a10a-f501d220d20e.png)

#### その画像群を入力したRealityCaptureの画面
カメラの位置を直接入力したのでBlenderと同じようになりました。
![15-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/4dacb657-3dfe-a868-5858-0555412cddc4.png)

#### 変換前のCOLMAPの画面
たまたまですが、モデルがZのプラス側に配置されました。
camera0の位置も原点から外れていました。
![15-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/22aa2ca4-6413-9b68-0113-c9bad1d2955e.png)

#### imagesR.txt; ref_images_pathに指定するファイル
RealityCaptureに指定したカメラ位置と同じ内容を記入しました。
![15-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/fce9903b-a279-8497-e694-a65f8dd5946e.png)

#### 実行
今回はGPSを使用しないのでref_is_GPSをゼロにしました。
![15-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/75b92c05-8427-ba21-d06f-feaa83d19c48.png)

#### 変換後のCOLMAPの画面
RealityCaptureと同じようにモデルがZのマイナス側に配置されました。
camera0の位置も原点に合いました。
![15-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/f4b1d85e-159e-edbb-98a0-ee6a11e3aa49.png)

#### 12/12に示したケーキのモデルデータを変換してinstantNeRFに入力した結果
上記の方法で作成したCOLMAPのモデルデータをテキスト形式でエクスポートして、12日目に説明した方法でtransform.jsonを作成し直しました。
画像の数が多いのでRealityCaptureのカメラパラメータのファイルからカメラ座標を取り出してまとめるpythonスクリプトを作成しましたが、一般的な内容なので割愛します。

https://qiita.com/nakmura/items/ec71ab21a74eeae57556

今回は再生結果が改善されました。
カメラの位置を教えてあげることでinstantNeRFの再生結果が改善する場合があることが分かりました。
![15-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/5d48a7df-3cb8-029c-61bd-f0b7b329618d.png)

#### 参考
https://qiita.com/Mas-sensyn/items/0784bf96fa9ae64b83b7#sparse%E3%81%AA%E7%B5%90%E6%9E%9C%E3%81%AE%E5%BA%A7%E6%A8%99%E5%A4%89%E6%8F%9B%E6%96%B9%E6%B3%95

https://colmap.github.io/faq.html#geo-registration
python ファイルの読み書き

## with文を使おう！
> with open(ファイル名, 'w', encoding=文字エンコード） as 変数:
    ……(ファイルを操作する処理)

※コロン「：」の後に、文を続けて書くこともできるが、pep8では推奨されていない
※with文を使わずopen関数でファイルを開いて書き込んだり、読み込んだりすることもできるが、最後にclose関数でファイルを閉じる必要がある。with文は、インデントブロックが終了すると自動的にファイルを閉じてくれるので、ファイルの閉め忘れ防止という意味でもwith文を使おう！

- open関数の第１引数は、操作したいファイル名を書く
- open関数の第２引数は、'w'(write:書き込み)、'r'(read:読み込み)、'a'(append:追加書き込み)、'r+'(読み込んでから書き込み)、'w+'(書き込んでから読み込み)などがある。第２引数を省略した場合は、'r'(読み込み)になる。
- open関数の第３引数（キーワード引数）は、ファイルの読み書きの文字エンコーディングを現す。utf-8(UTF-8), shift-jis(シフトJIS), enc-jp(日本語EUC)などがある。

## ファイルに書き込んでみよう！

test.txtというファイルを作成して書き込んでみる。
 >※指定したファイルが存在しない場合、ファイルを作成し、指定したファイルが存在する場合は、上書きが行われる。注意！！
~~~python:exam.py
with open('test.txt', 'w', encoding='utf-8') as file:
    file.write('HELLO!\n')
    file.write('ENJOY PYHON!\n')
~~~

~~~python:test.txt
HELLO!
ENJOY PYHON!
~~~
test.txtが作成され、文字列が出力されました。

## 作成したファイルを読み込んでみよう。
~~~python:exam2.py
# 第２引数を省略。'r'が適応される
with open('test.txt', encoding='utf-8') as file:
    # test.txt1の全文を読み込み
    print(file.read())

>>>
HELLO!
ENJOY PYHON!
~~~
enumerate関数を使うと出力時に番号を付けることも可能！
~~~python:exam2.py
# 第２引数を省略。'r'が適応される
with open('test.txt', encoding='utf-8') as file:
    # test.txt1の全文を読み込み
    for number, text in enumerate(file, 1):
        print(number, text, end='')

>>>
1 HELLO!
2 ENJOY PYHON!
~~~

## csvファイルを書き込もう！
>import csv
>
>with open(ファイル名, 'w', encoding=文字エンコード, newline='') as 変数：
    csv.writer(ファイル).writerows(イテラブル）
※newlineは改行を抑制する効果がある。これを指定しないと改行が余分に出されて、文と文の間に空行が入ってしまうため、newline=''のようにする。
※writer(ライター）　writerows(ライトローズ）

>csv.writer(ファイル名).writerows(イテラブル）※1行だけ書き込む
>
>変数 = csv.writer（ファイル名) # 変数に代入して使う
変数.writerrow(イテラブル）

~~~python:exam3.py
import csv

memo = [('beef', 600), ('pork', 500), ('chiken', 400)]
with open('memo.csv', 'w', encoding='utf-8', newline='') as file:
    csv.write(file).write
    csv.writer(file).writerows(memo)
~~~

~~~python:memo.csv
beef,600
pork,500
chiken,400
~~~
## csvファイルを読み込もう！
>with open(ファイル名, encoding=文字エンコード) as 変数：
    for 変数 in csv.reader(ファイル名):
        ……
  ※reader()は、イテラブルとして働き、値をリストで返す。
~~~python:exam4.py
import csv 

with open('memo.csv', encoding='utf-8') as file:
    for row in csv.reader(file):
        print(row)
    file.seek(0)
    print([tuple(i) for i in csv.reader(file)])
>>>
['beef', '600']
['pork', '500']
['chiken', '400']
[('beef', '600'), ('pork', '500'), ('chiken', '400')]
~~~
【IchigoJam】爆弾ゲーム

[IchigoJam](https://ichigojam.net/) で爆弾ゲームを作ってみました。

# 爆弾ゲーム

爆弾の前にスイッチが何個か並んでいます。
そのうち1個だけ、押すと爆弾が爆発するスイッチがあります。

* 複数人で遊ぶ場合
  * まだ押されていないスイッチを順番に1個ずつ押していきます。
  * 爆弾を爆発させた人が負けです。
* 1人で遊ぶ場合
  * スイッチを押していきます。
  * 爆弾を爆発させたらゲームオーバーです。
  * 爆弾を爆発させずに押していないスイッチを1個だけにできたらクリアです。

# 仕様

ゲームを開始すると、1～8の8個のスイッチが表示されます。
1～8の数字キーを押すことで、スイッチを選択します。
まだ押されていないスイッチを選択すると、「ポチッ」と表示されます。
数秒後、押されたのが爆弾が爆発するスイッチだった場合は、「ドカーン！！」と表示されてゲームが終了します。
そうでなかった場合は、「セーフ！」と表示され、次のスイッチの選択に移ります。

# プログラム

```
10 ' ﾊﾞｸﾀﾞﾝ ｹﾞｰﾑ
20 N=8
30 FOR I=0 TO N-1:[I]=1:NEXT
40 [RND(N)]=2:CLS:X=16-N
50 LOCATE10,5:?"ﾊﾞｸﾀﾞﾝ ｹﾞｰﾑ"
60 FOR I=0 TO N-1
70 LOCATEX+I*2,15:?CHR$(49+I)
80 NEXT
90 LOCATE9,10:?"ﾄﾞﾉ ｽｲｯﾁ ｦ ｵｽ?"
100 K=INKEY()-49
110 IF K<0 OR N<=K GOTO 100
120 IF [K]=0 GOTO 100
130 LOCATEX+K*2,14:?CHR$(#ED)
140 LOCATE9,10:FOR I=1 TO 14
150 ?CHR$(0);:NEXT
160 LOCATE10,20:FOR I=0 TO 3
170 IF I=0 ?"ﾎﾟﾁｯ"; ELSE ?".";
180 T=60:GOSUB 280:WAIT T
190 NEXT
200 IF [K]=2 GOTO 310
210 ?"ｾｰﾌ!":[K]=0
220 T=180:GOSUB 280:WAIT T
230 LOCATEX+K*2,15:?"_"
240 LOCATEX+K*2,14:?CHR$(0)
250 LOCATE10,20:FOR I=1 TO 11
260 ?CHR$(0);:NEXT
270 GOTO 90
280 IF VER()<13208 RETURN
290 IF VER(1)=3 T=T*25/96
300 RETURN
310 ?"ﾄﾞｶｰﾝ!!"
```

# 解説

* 10行目 : タイトル
* 20行目 : スイッチの数の設定
* 30行目 : スイッチの状態の初期化
* 40行目 : 爆破スイッチの選択、スイッチの描画位置の決定
* 50行目～90行目 : 描画
* 100行目 : キー入力の読み込み
* 110行目 : スイッチに対応しないキーを弾く
* 120行目 : 既に押されたキーを弾く
* 130行目 : 押されたスイッチの上にキャラクターを描画
* 140行目～190行目 : スイッチを押したときの演出
* 200行目 : 押されたスイッチが爆破スイッチだったかの判定
* 210行目～220行目：「セーフ！」の表示
* 230行目～270行目：ボタンの選択に戻る
* 280行目～300行目：IchigoJam web 用の待ち時間の調整
* 310行目 : 「ドカーン！！」の表示

# 実行結果

<iframe width="560" height="315" src="https://www.youtube.com/embed/Z1dnR4fPgxg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 改造のアイデア

* 爆弾の絵を表示する
* スイッチの表現を改良する
* 効果音をつける
* サーボで風船を割るなど、爆破を物理的に表現する
* コードを切るなど、スイッチの選択を物理的なもので行う

# おわりに

※IchigoJamはjig.jpの登録商標です。
エンジニアとして1年働いてみて大変だったことや感じたこと

# はじめに
こんにちは。グロービスでナノ単科・nano-MBAの開発をしている野口です。
今回は私がエンジニアとして1年働いてみて大変だったことや感じたことを書こうと思います。

前回の記事はGraphQLについて書かせて頂きました。もしよろしければご覧下さい。

https://qiita.com/kohei-noguchi/items/f93c6953ed9346d79a70

# エンジニアを目指したきっかけ

#### WEBスクレイピングのプログラムを作ったのをきっかけに

そもそも何故私がエンジニアになりたいと思ったのかをお話しすると、前職でアウトソーシングサービスをしていた頃に遡ります。クライアントから様々な依頼がある中に、インターネット機器のキッティングという作業がありました。


キッティングとは簡単に言うとPCやアクセスポイント、ルーターなどの精密機器を動く様に設定し、すぐに使用できる状態にしてクライアントへ発送することです。その精密機器の設定はPCに繋いでブラウザで行うのですが、最初は全て手動で設定していました。

**ID/PASSを入力して次にここの項目にはこの値を入れて再起動して設定値が合っているか確認して・・・** という作業を月に何百台、多い時は千台くらいやっていました。

そんなある時、**「当たり前の様に手動でやってるけど大変だし自動化したいな」** と思い、自動化のプログラムを書こうと決意しました。PythonでSeleniumを使った簡単なWEBスクレイピングのプログラムです。これをキッカケに**エンジニアってどの様な仕事なんだろう** 、**チーム開発でサービスを作るって面白そう** と思う様になりました。

# いざエンジニアになってみて

### 環境構築に2~3日かかる

未経験・ベテランに関わらず新しいプロジェクトに参画したら最初に環境構築をすると思います。
私もPCを貸与されて 「まずbackendとclientの環境構築終わらせて。わからない所があったら言って」と言われ環境構築を進めることに。しかし当時の私は **「環境構築ってなんだ？何をすれば良いんだ？」** といった具合でそこから調べることに。

>プログラミングの環境構築とは、プログラミングを始めるために必要不可欠な開発環境を準備することです。
https://japan-design.jp/programming/4059/

なるほど、ツールとかインストールして自分のPCで開発できる様に準備することか。そしてその手順はgithubのREADMEに書いてあるのか。早速始めよう！

#### コマンドの意味を理解せずコピペで進める

このコマンドは何をしているのかを理解せずに、しかもそのコマンドの実行結果をしっかり読まずにコピペして進めていました（絶対ダメ）。エラーが起きた場合、ログを読めばそこに解決のヒントが書いてあったりしますが、当時の私は読まずに1人で悪戦苦闘していました（そこにヒントが書いてあることすら知らなかった）。

#### 分からないことが分からない

チームの皆さんに聞こうにも自分が何をしていてどこで躓いているのか、何を達成したいのか、試したことは何かを上手く言語化できず質問の仕方さえもわからない状態でした。やっていることを理解していないままコピペしているだけだからそりゃ当然でしょと思われると思いますが、今の私もそう思います。

なので私が取った行動は、オフィスにいる先輩の所までPC片手に行って **「ここが分からないので教えて下さい」** という物凄いアバウトな聞き方をしていました。

今思うと、何て雑なお願いをしているんだと恥ずかしくなりますが、当時の自分はこれしかやりようがなく必死でした。そんな雑なお願いにチームの皆さんも嫌な顔せず丁寧に教えて頂いたので本当に感謝しかないです。

環境構築の他にも、エンジニアになって最初の1ヶ月は

- Sequel Proで本番とstgのDBに接続する
- DBの各テーブルのカラムの内容とデータ型を調べる
- 開発で使用している技術・ツールについてインプットする

などの課題を進めていました。この時は、 **「自分はエンジニアとしてやっていけるだろうか。チームのエンジニアの方みたいにバリバリ開発できる様になるのだろうか。凄い大変な世界に来てしまったな。」** と不安でいっぱいでした。

# 1年経過して感じたこと

チームの皆さんのおかげで何とか1年続けることが出来ました。1年前は右も左も分からず、分からないことが分からない状態だったので当時と比べればかなり成長したと思います。そんな中感じたことは、

#### チームの皆さんへの感謝

未経験の私に皆さん丁寧に教えて下さいました。本当に感謝しています。（まだまだ聞きまくっていますが）
早く私も誰かの問題や困っている課題に対して解決に導ける様な存在になりたいと思います。

#### 問題解決力が足りない

自分が対応している問題や課題に対して、原因となる箇所の特定やその解決策を考える力が足りないと感じました。解決策を複数パターン考えらえる様に柔軟性や創造性を身につけていきたいと思います。

#### コミュニケーション能力の重要性

リモートワークをしている方が多く、基本slackでコミュニケーションを取るのですが自分が何を伝えたいのかをはっきりさせないと相手に伝わらないしダラダラと長い文章になってしまいます。伝えたい要点をまとめる能力とリモートワークの難しさを感じました。


# 今後の抱負

早くエンジニアとして1人前になることが目標です。何を持って1人前と言うかですが、私が考える1人前のエンジニアは

- 自分が参画しているプロジェクトで使用している言語のスキルをもっと磨く（狭く深く）
- チームで問題や課題が起きた時に、原因を突き止めて解決策を提案できる様になること
- チームの誰かが困っていたら助けられる様になること
- 開発中に躓いて、質問する時は何を達成したいのか、何に困っているのか、何を試したのか、どんなエラーなのかを分かりやすく明確にする
- 流行り廃りが激しいこの業界の変化に対応できる様に、仕事で使用している言語・プラットフォーム以外のものを勉強してスキルのレパートリーを増やしていく

もちろん上記以外にやらないといけない事はたくさんあると思います。そんな時は是非コメント下さい。
最後までお読みいただきありがとうございました。
GoでTensorFlow！Pythonに支配されるな！ 【環境構築編】

# はじめに
この記事はC3 Advent Calendar 2022 11日目の記事です.
## 対象読者
- 機械学習をやってみたいけど何から始めていいかわからない人
- Goを使って何かしてみたい人
- `機械学習=Python`という固定概念に囚われたくない人
- Goが好きな人
## なぜ，GoでTensorFlowを使うの？
現在，機械学習を行う際の使用言語としてメジャーなのはPythonです．確かにPythonはライブラリが充実しており，参考記事も多く手軽に機械学習を用いたプロダクトを作成することも可能です．**ただ，それって普通で面白くなくね？** せっかく世の中にはいくつもの言語があるわけです．〇〇には△△を使うのが一般的だからっていう理由で選んじゃっていいんですか． **どうせなら自分の好きな言語でやりたい！** ということで今回は僕の好きな言語の一つである**Go**を使って機械学習を行なっていきたいと思います！今回は環境構築編です！

# 環境構築
GoでTensorFlowを動かすための環境を作る方法はいろいろありますが，今回はDockerを用いて，GoでTensorFlowの環境を作っていきます．
この記事ではDockerの環境構築は割愛させていただきます．
以下のサイトを参考に環境を用意してください．
https://docs.docker.jp/docker-for-windows/install.html
### 実行環境
- wsl2
- Ubuntu 20.04.4 LTS
- Docker version 20.10.16
- go version go1.18.3 linux/amd64
(M1/M2 Macではアーキテクチャの違いで動作しませんのでご注意ください)
### 手順
##### 1. 以下のgithubリポジトリをcloneしてくる
https://github.com/K-Kizuku/go-tensorflow/tree/create_environment
```
git clone -b create_environment git@github.com:K-Kizuku/go-tensorflow.git
```
##### 2. cloneしてきたリポジトリで以下のコマンドを打ってDockerのイメージの作成
※イメージの作成には少々時間がかかりますが，気長に待ってください
```
docker image build -t tensorflow:v1 .
docker run --name tensorflow-container -it tensorflow:v1 /bin/bash
```
##### 3. 環境構築完了
```
Hello from TensorFlow version 2.10.0
```
上記のような表示が出れば環境構築は完了です．これで，GoでTensorFlowを使う準備が整いました．お疲れ様でした

# 最後に
今回は環境構築編ということで軽い内容でしたが次回以降しっかりTensorFlowを用いて機械学習をしていきたいと思うので，是非ご覧ください！！


明日はHarappa_planeさんの「同人即売会に行こう！」です
intel Mac に Windows 11 をインストールする　（超簡単）

![IMG_1025.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/01fd92cd-246e-6f69-6ab2-ee26490c6097.jpeg)
intel Mac に(限らず)、windows 11をインストール際にチェックされるTPM2.0を回避する手順です。
Windows 11 22H2 への更新の際に、Rufas(ブータブルUSBディスクを作るツール)を使う方法です。
超簡単でした。
下は21H2からのアップデートのことしか書いていませんが、Windows 10からもできるらしい。


# 私の環境
 - intel Mac (Widows 11 21H2インストール状態からの更新インストール※）
 - 中身が消えてもよいUSBメモリ(8GB以上)　
 ※ Windows 10からの更新インストールもできるらしいです。

# 1. 準備
(1) Windows 11 ISOイメージをダウンロード
https://www.microsoft.com/software-download/windows11
私は、英語版をつかうので、Win11_22H2_English_x64v1.iso
をダウンロードしました。

(2) Rufusをダウンロード。
https://rufus.ie/en/
自分は、rufus-3.21.exeをダウンロード。
(rufus-3.21p.exe(ポータブル版)も、rufus-3.21.exe(非ポータル？版)もバイナリは同じ。)

 
# 2. インストール媒体を作成
(1) rufus-3.21.exeを起動
![1_RUFAS_SETTING.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/a5aec133-f973-5bfd-678c-24543347d394.png)
Deviceには、ターゲットのUSBメモリを選択。(写真は、Dドライブに挿入したUSBメモリ)
Boot SelectionにはダウンロードしたISOイメージファイルを選択して
[START]を押す。

(2) rufusのオプション設定
![2_RUFAS_CONFIG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/bad5fa5a-6882-9896-43ba-317c9b5a4a1e.png)
デフォルトのまま[OK]を押す。(一読して理解して選択してもよいです。）
最上段のチェック項目がTPM2.0回避の設定。

USBメモリの中身が消える警告画面が表示されるので[OK]を押して継続。
資源がコピーされることを待ちます。


# 3. いざインストール
(1) USBメモリに集約されたSetup.exeを起動。
私は今回は更新なので、windows OSが起動した状態(USB媒体からのブートは不要)から実施。
![3_Launch_Setup_exe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/9c220d6a-13a9-c50b-d3a6-a62a18f3e63c.png)
"Change how Setup downloads updates"を選択。

(2) オンラインで更新されないために・・・
![4_Donot_go_online.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/74bb4b1e-e1c6-1b68-8e47-f4882367fa7a.png)
"Not right now"を選んで[NEXT]を押します。（なるほど！）
あとはEULAを読んで[Accept]を押したり淡々と進めます。
数十分すると、更新作業が完了します。


# 4. さてRufasはどうやって・・・？
WinMergeで、オリジナルのISOの中身と、USBメモリのコンテンツを比較すると、
![Diff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/f6dac714-58af-67ea-00e9-ebd65a5f3b0d.png)
Rufasが何をやっているか観察することができます。


# おまけ
構造全体を把握しようとすると、WinPEの出番です。

https://qiita.com/kmatsuura/items/a57198c27549497cde9d

https://qiita.com/kmatsuura/items/9d098bb20f1c94851a72

2022/12/14 スマホで読みにくいのでインデントを修正。旧ドキュメントへのリンクをはりました。他微修正。
Goのnet/http Requestでヘッダーの大文字小文字を厳密にしたい

本記事は[ディップ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/dip-dev)の5日目の記事です。
言い訳をすると１２月頭から体調を崩してしまい、寝込んでいました。
---言い訳終了---

とあるAPIを叩くためのクライアントライブラリを作成していたところ、APIを受ける側がヘッダーに特定のデータを要求している仕様となっていました。
Goの`net/http`パッケージを利用した実装ではたいてい下記のような書き方になると思います。

``` go
func ApiCall() {

    req, err := http.NewRequest("GET", "https://example.com", strings.NewReader(""))
    if err != nil {
        //なんらかのエラー処理
    }
    req.Header.Set("New-RequestHeader", "header-data")

    //ここでdebug printします。
    fmt.Printf("%v \n", req.Header)

    c := hrrp.DefaultClient
    res, err := c.Do(req)
    if err != nil {
        //何らかのエラー処理
    }
    defer res.Body.Close()
    //後続の処理とか

}
```

debug printの結果
```
map[New-Requestheader:[header-data]]
```


httpの仕様では、ヘッダーの大文字小文字は区別しようようですが、前述のAPIでは厳密にヘッダーKeyの大文字小文字を区別するような仕様となっており`New-RequestHeader` というkeyでないとエラーになるようなものでした。

Goの`req.Header.Set`や`req.Header.Add`は下記関数を利用し、データをセットしているようで、ハイフン直後以外のデータはすべて小文字に変換されてしまうという仕様です。
https://pkg.go.dev/net/textproto#CanonicalMIMEHeaderKey

ですので、↑のSampleでは、Request時にヘッダーが`New-Requestheader`となってしまい、APIサーバからRequest不正のエラーが返ってきてしまう状況でした。



## 解消方法

解消方法を探していたところ、そもそも`req.Header`は`map[string][]string`型のため、直接データを入れてしまう方法というところに行き着きました。
情報ソースは下記ブログです。
※この記事とまんま同じ事が書いてあるような・・・
https://dhdersch.github.io/golang/2016/08/11/golang-case-sensitive-http-headers.html

解消版のSample sourceは下記となります。

``` go
func ApiCall() {

    req, err := http.NewRequest("GET", "https://example.com", strings.NewReader(""))
    if err != nil {
        //なんらかのエラー処理
    }
    req.Header["New-RequestHeader"] = []string{"header-data"}

    //ここでdebug printします。
    fmt.Printf("%v \n", req.Header)

    c := hrrp.DefaultClient
    res, err := c.Do(req)
    if err != nil {
        //何らかのエラー処理
    }
    defer res.Body.Close()
    //後続の処理とか

}
```

debug printの結果
```
map[New-RequestHeader:[header-data]]
```

これは詰んだのでは・・・？と思ったのですが、意外と簡単な解決方法がありました。
雑な記事となってしまいましたが、皆さんのお役に立てればと思います。

以上
40代から始めた転職活動

この記事は「[エンジニア転職活動ハックをシェアしよう！ by キャリアデザインセンター「Direct type」 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/directtype)」の12/14日分の記事になります

転職に関してということで、3年前に転職をしたときのことを、そろそろ時効だろうということで書いてみたいと思います。

## 転職に至った背景
正直言って、給料面や評価面で不当な扱いを受けているとかそういう話はありませんでした。むしろ過分な評価を頂いていたとすら感じます。
一方で、それであるがゆえにプレッシャーもあり、更に担当しているプロダクトの対象領域というか業界的に、将来的に見て衰退していくような不安がありました。
会社としてみたときに、プロダクトは複数あったためにずっとそのプロダクトをするという訳では無いのでしょうけれど、自分の立ち位置的には離れることは難しい。
更にいうと、そのプロダクトに対しての情熱を注ぐということが環境含めて様々な理由で難しくなってきてしまったということが主な理由です

漠然と、別のサービスやプロダクトを自社で展開している会社を思い描いて転職活動を開始しました

## 粉々になる自信
それまで、一つの会社に20年近くいたために、社内の事情や人間関係にも精通。会社の中で物事を回すことに関しては問題なかっただけに、採用面接で話をしたり落とされたりするたびに、それまで築いてきた自信は崩れていきます。

年齢的にも40代ということもあり、書類時点で落とされることもザラでした。
当たり前の話ですが、面談に出てくる人はそれなりの知見を持った人ですし、自社サービス・プロダクトを展開している会社の場合20代～30代の優秀な方々の質問にさらされます。

結局、自分の実力では拾ってもらえないのではないか
仮に採用試験をパスしたとしても、すぐに見限られてしまうのではないか
伸びしろを考えると、どう考えても若い人を雇ったほうがいいのではないか

色々と考えてしまい、書類選考の結果すら恐怖になってきます。

挙句の果てに、面接を受けに行った相手の会社の取締役の方に、現職にとどまったほうが良いのではないか？というアドバイスまで受ける始末です。

## 前提を見直すとともに諦めない
IT業界。エンジニアとしてみたときに、決して一般的目線で見て輝かしい実績を持っているわけではない状態で、自分ではまだ若いと思っていモテ年齢的にも40代はすでに難しい条件。
普通に考えれば所帯持ちで転職するべきではないのかもしれない。

ただ、今の場所に居続けたいのか？そして、転職先にこだわっていられるのか？に関して見直すべきなのかもしれないと考えました。
要するに、何を優先させるのか？ということですね。

転職することを目的にするべきではなく、転職で何を実現するのか？

こういう言葉はよくある話だと思いますし、間違いとは思いません。
ただ、「何を実現するのか？」が"環境を変える"であったり、ひいては"転職"であることもあながち間違いとも思いません。

あまりにも書類選考や面接で落ちていたために精神的に厳しい時期もありましたが、転職活動を1年以上に渡って続けることになりました

## 出会いは突然に偶然に
転職サービスは非常に多いです。

私はいくつかのサービスにも登録していましたが、基本的にはエージェントを主体に動いていましたため、それほど転職サービスへは力を入れていませんでした。

結果的には、登録していた転職サービスからのダイレクトリクルーティングを使ってのカジュアル面談からトントン拍子に話が進んでいき、転職に至りました。

本当、何がおきるかわかりません

私の転職が成功だったのか？失敗だったのか？は難しいところだと考えています。
給料や福利厚生などは前職は非常に充実していたために現職のほうが劣ります。

一方で、前職ではグループ会社間での社内政治や、担当プロダクトに対するわだかまりなどがあったので、そういったストレスで考えるのであれば現職に軍配が上がります。

何が成功か、失敗かというのは結局のところ、自分で成功にしていくしか無いと思うので、頑張っていくしかありません。

私は年齢が行ってからの初転職ということでとても大変だったと感じています。
ただ、その中でもダメ元で登録したサービスから決める事ができたという非常に運のいい経験をさせてもらいました。
諦めず、取れる手段は取れるだけ取る。
一つのやり方にこだわらずに、見直しをかけて回していく。

転職活動も、常にアジャイルにまわしていかないといけませんね。
WindowsにTeraTermインストール

# 概要

この記事では…

* インストーラのダウンロード先。
* インストール終了まで。

という環境作るところだけ書いてます。

# やり方

ダウンロードサイト行く。

https://ja.osdn.net/projects/ttssh2/releases/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4d2dec52-3bda-0d70-4838-7e4a0c0ec0cd.png)

最初「4.106より4.98の方がバージョン上じゃない？」と思った。
けど、よくよく考えてみたら
106（百六） > 98（九十八）
で4.106の方が最新じゃん、って気づいた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4a194607-ed05-a953-9f12-935056c8afcf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c7b175f7-a951-2449-2a3f-2cbc2b57c53a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4c6ebd44-da3a-32ba-f309-a6b81406c549.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3915e318-0363-2c9e-e140-564f9b889608.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/eb7f6421-aa8d-e2ef-2ea6-ca329c6cc434.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e31ce20f-cb94-2f1a-6867-462ee385645b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/19159792-9753-25a3-ae02-f3de2b1d78da.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/96ba5334-bf66-0511-2fea-aec45fdbd84a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ed8bfcd4-a01b-1542-b7fc-b5719515adb4.png)

# 蛇足

Windows10からUbuntuの様子見る時に ↓ リモートデスクトップしてた。

https://qiita.com/waokitsune/items/fec2ec852d0d89832895

でも認証の画面が何回も出てくるの面倒なのでTera TermでSSH接続してサーバーメンテしようと思った。

# バージョン

Windows 10 Home 21H2 19045.2251
Tera Term 4.106
文字列出力を自動で引用符でくくる

本記事では、Fortran の write 文で文字列を書き出すときに、その前後に自動的にアポストロフィまたはクォーテーションマークを付ける方法を紹介します。

Fortran の list-directed I/O での空白入り英文字列の扱いが楽になります。空白の入った英文字列などを、CSV ファイルで出すときにも便利かと思います。

# Open 文による属性の変更

まずプログラムと実行結果を示します。

三回 print *, 'This is a pen.' を繰り返しますが、open 文で delimiter 属性を変えることによって出力文字列が '' や "" によって囲まれるようになります。

### プログラム
```fortran
    program strings
        use, intrinsic :: iso_fortran_env, only : output_unit
        implicit none

        print *, 'This is a pen.'

        open(unit = output_unit, delim = 'apostrophe')
        print *, 'This is a pen.'

        open(unit = output_unit, delim = 'quote')
        print *, 'This is a pen.'

    end program strings
```

### 実行結果　gfortran
```
 This is a pen.
 'This is a pen.'
 "This is a pen."
```
## iso_fortran_env 中の output_unit

いまここで Fortran 標準出力の属性変更を行っています。標準出力は古くは 6 番にあてられていて、のちに unit = * が推奨されるようになりました。最近 Fortran 2008 以降では intrinsic module の iso_fortran_env の中の output_unit に番号が定義されています。

print 文も標準出力に出力することになっていますので、output_unit の属性を変えると print 文の出力結果も変化します。

:::note warn 
ところが intel fortran では output_unit の属性を変えても write(*, *) や print の属性が変わりませんでした。コンパイラの問題だとは思いますが･･･
:::


## open 文の delim 属性

open 文の中には delim (delimiter) 属性があって、これを変えることで文字列を自動で引用符で囲めます。delim の取りうる引数は
1. 'none'
2. 'apostorophe'
3. 'quote'
の三種類で、それぞれ 1.引用符無し、2.アポストロフィ('')、3.クオーテーションマーク("") となります。デフォルト値は 'none' になっています。

例題では標準出力を用いましたが、一般的なファイルでも delim は使えます。

## 多重 open

Fortran の open 文は close せずに開くと、基本的には勝手に close して新たに open します。しかし特定の場合には、単なる属性変更になります。delim はこの属性変更の例になっています。上記プログラムでもいちいち close せずに、次々 open しています。

これに関してはややこしい規則があるので Dr. Fortran こと Steve Lionel 氏の記事を参照してください。

https://stevelionel.com/drfortran/2020/05/25/doctor-fortran-in-the-modes-they-are-a-changin/

# まとめ

以上、Fortran の write 文で文字列を書き出すときに、その文字列の前後に自動的にアポストロフィまたはクォーテーションマークを付ける方法を紹介しました。

Fortran の list-directed I/O での読み込み時は、コンマまたは空白を区切り文字にするので、空白入りの英文字列があると単語ごとに区切られてしまいますが、英文字列が引用符で囲まれていると全体を１個の要素と見なします。この様な場合 delim を用いると出力時にいちいち英文字列を囲む引用符を write 文につけずに済むので便利かと思います。


# 謝辞

この記事は、最近 implicit_none さんから別記事に頂いたコメントから着想を得ました。感謝いたします。

https://qiita.com/cure_honey/items/1a87fc88608757676c8b#comment-36184e306b6de2ee798d