OmniAICreator/Qiita-1.07M huggingface dataset:
7年目のエンジニアがキャリアを振り返って思う「やっておけばよかった」こと

# はじめに
記事投稿キャンペーンのテーマが「[自分のエンジニアとしてのキャリアを振り返ろう！](https://qiita.com/official-events/72b44470c9c08f6f080b)」ということで、これまでの約７年間のエンジニアとしてのキャリアを振り返って「やっておけばよかった」と思ったことを書き残したいと思います。

# ざっくり自己紹介
- 1994年生まれ
- 四年制文系大学卒業 → 新卒でなんの知識もなくIT業界へ
- 転職経験なし
- 自社サービス、受託、SESでの開発を経験
- MPA、CSRのみを使ったSPA、Web API、iOSアプリ、Androidアプリ、Android用SDKの開発を経験
- 自社チーム内でのリーダーと客先チーム内でのサブリーダーを通して、合計3年のマネジメントを経験
- 最近はReact + TypeScriptを使ったフロントエンド開発をやっている

# やっておけばよかったこと

## 基礎を固める
基本情報技術者試験の範囲やコンピューターサイエンスのような、陳腐化しにくい知識をイメージしています。

### なぜそう思うか
- 基礎があるかどうかで新しい技術の勉強をしたときの理解度に差が出る
- 基礎がある前提で会話が行われたり、本や記事などの読み物が書かれていることがある
- 仕事相手から基礎が身についてないと思われてしまうと印象が悪いかもしれない

自分は必要なことを必要なタイミングに調べるやり方でここまできてしまいました。一度身につければずっと役立つので、キャリアの最初の方で身につけておけばよかったなと思っています。

### どうすればよかったか
- IPAの資格試験、例えば基本情報技術者試験の勉強をする
- 本やサイトでコンピューターサイエンスに関する勉強をする

これは体系的に勉強するしかないと思っています。自分のように必要なことを必要なタイミングに調べるだけではあまり身につかない、というか実際に自分が身についていない気がします。ただし、勉強して面白いと思えるのか、続くのかというは不安要素であり、自分がやってないのでわかってないところです。

## アウトプット
コードを書いてGitHubに残したり、記事を書いたりすることをイメージしています。

### なぜそう思うか
- ただ学んだり業務で経験するだけよりも身になる
- エンジニアとしての評価材料になる
- 忘れてしまったり言語化されてないことで、もう一度考えたり調べなくて済む

今考えればやらない理由はないのですが、なぜかアウトプットするという考えにならなかったり、理由をつけてアウトプットしないという選択をキャリアの前半ではしてしまっていました。特に経験や自分の考えをアウトプットしてなかったのは、忘れてしまったり言語化されてないことで困ったことが何度もあるので後悔しています。

### どうすればよかったか
- 形式はともかく、とにかくアウトプットする

理想はオープンにすることですが、心理的ハードルがあるのも理解できます。とにかく脳にだけ残しておこうとするのは良くないので、まずはオープンにしなくとも、ローカルのメモ帳でもいいので残しておくことが大事だと思っています。

## 技術的な強みを作る
言語だったり領域だったりなんでもいいのですが、自分は技術的にこれが強いです！と言える状態をイメージしています。例えば「Javaに強い」「フロントエンドに強い」「DBに強い」などが考えられます。

### なぜそう思うか
- 仕事を探す場合に有利
- 自分がどんな人か理解してもらいやすい
- 自分に自信が持てる

自分の場合は広く浅くになってしまっていて、自分は技術的にこれが強いです！と言えるものがありません。技術的な強みをアピールできた方が、エンジニアとして生きていくうえで有利だと思います。

### どうすればよかったか
- 自分がハマれる技術を見つけて学び続けて、できれば仕事で長期間携わる

どうすればハマれる技術が見つかるのか？は色々やってみるしかない気がしますが、案件ごとに使う技術がバラバラだとそれぞれの習熟度が上がらず、結果として今の自分のように広く浅くで強みがよくわからないエンジニアになってしまいます。なのでそれは避けるように意識すべきだと思います。

## 転職活動やキャリア相談
結果的に転職するかどうかは置いておき、転職のための準備や選考、外部へのキャリア相談など、キャリアを見直して変える選択肢を持って行動することをイメージしています。

### なぜそう思うか
- 転職活動を意識してキャリアを振り返ったりスキルを棚卸しすることで、やりたいことや自分に足りないものが整理される
- 客観的な自分の評価やアドバイスをいただくことで、新たな道がひらけたり今後の方針のヒントになる

自分は転職活動を一回もしてきませんでした。これは転職しなくても様々な経験できる環境だったことが大きく、そのためあまり考えてませんでした。しかし外部に評価を求めることで、エンジニアとしてより良い歩みができたのではないかと思っています。

### どうすればよかったか
- まず誰かと話す

誰かとキャリアについて話すだけでも考えるきっかけになるので、いきなり転職エージェントと話すのが嫌な場合は、職場の人やエンジニア友達などととにかく話してみるべきだったと思います。

# おわりに
この記事を書くにあたって、昔を思い出したり、改めてキャリアについて考える機会になり良かったです。自分が思った「やっておけばよかった」ことを読んでいただき、同じ後悔をするエンジニアが一人でも減ることを願っています。
pdfsharpcore

```
using PdfSharpCore.Drawing;

class Program
{
    static void Main(string[] args)
    {
        // PDFドキュメントを作成
        PdfDocument document = new PdfDocument();
        PdfPage page = document.AddPage();
        XGraphics gfx = XGraphics.FromPdfPage(page);

        // フォントとテキストを指定
        XFont font = new XFont("Arial", 12);
        string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";

        // テキストの描画
        XRect rect = new XRect(100, 100, 400, 200); // 描画領域
        gfx.DrawString(text, font, XBrushes.Black, rect, XStringFormats.TopLeft);

        // 両端揃えのためのカスタムロジックを実装
        rect = new XRect(100, 300, 400, 200); // 描画領域
        DrawJustifiedText(gfx, text, font, XBrushes.Black, rect);

        // PDFファイルに保存
        document.Save("output.pdf");
    }

    static void DrawJustifiedText(XGraphics gfx, string text, XFont font, XBrush brush, XRect rect)
    {
        string[] words = text.Split(' ');
        float totalWidth = gfx.MeasureString(text, font).Width;
        float spaceWidth = (rect.Width - totalWidth) / (words.Length - 1);

        float x = rect.X;
        float y = rect.Y;
        foreach (string word in words)
        {
            gfx.DrawString(word, font, brush, new XPoint(x, y));
            x += gfx.MeasureString(word, font).Width + spaceWidth;
        }
    }
}
```
【Power Apps】 文字コードを取得するユーザー定義関数

# はじめに
こんにちは。
ココイチでカキフライカレーが食べたい男です。

以前、こんな記事を投稿しました。

https://qiita.com/n2Mj7Lg3cxNcFtJ/items/bfb263799b3115f5824a

「Char(65) とすると "A" が返ってくる。フツーに考えたら、Code("A") とかで 65 って返ってきてほしいじゃん」みたいな事が書いてあります。

なんか、ユーザ定義関数が使えるようになっているらしいので、
上記の「Code("A") で 65 が返ってくる」関数を作ってみました。

### 補足
- ユーザ定義関数は、まだプレビューです。（2024/3/14時点）
- Power Apps の設定はこちらを参考にしました。 
→ https://koruneko.hatenablog.com/entry/2024/01/22/075820

# コード

```
Code(ch:Text):Number=Switch(ch," ",32,"!",33,"""",34,"#",35,"$",36,"%",37,"&",38,"'",39,"(",40,")",41,"*",42,"+",43,",",44,"-",45,".",46,"/",47,
"0",48,"1",49,"2",50,"3",51,"4",52,"5",53,"6",54,"7",55,"8",56,"9",57,":",58,";",59,"<",60,"=",61,">",62,"?",63,"@",64,
"A",65,"B",66,"C",67,"D",68,"E",69,"F",70,"G",71,"H",72,"I",73,"J",74,"K",75,"L",76,"M",77,"N",78,"O",79,"P",80,"Q",81,"R",82,"S",83,"T",84,"U",85,"V",86,"W",87,"X",88,"Y",89,"Z",90,
"[",91,"\",92,"]",93,"^",94,"_",95,"`",96,
"a",97,"b",98,"c",99,"d",100,"e",101,"f",102,"g",103,"h",104,"i",105,"j",106,"k",107,"l",108,"m",109,"n",110,"o",111,"p",112,"q",113,"r",114,"s",115,"t",116,"u",117,"v",118,"w",119,"x",120,"y",121,"z",122,
"{",123,"|",124,"}",125,"~",126,0);
```

上記のコードを Formulas に記載し、**Code("A")** のように呼び出せば使えます。

また、１つ後、１つ前の文字を取得するユーザ関数も作ってみました。
```
NextChar(ch:Text):Text=If(And( Len(ch)>0, Code(ch)<126),Char(Code(ch)+1),"");
PrevChar(ch:Text):Text=If(And( Len(ch)>0, Code(ch)>32),Char(Code(ch)-1),"");
```
**NextChar("B")** は **"C"**、**PrevChar("B")** は **"A"** が返ってきます。
Docker内で静的なファイルのエンドポイントを環境に合わせて書き換える

FastAPIでホストしているstaticファイル群（HTML＋JavaScript）があります。

main.jsから、FastAPIのAPIをたたくのですが、
テスト用環境と本番用環境でエンドポイントが異なります。

     // テスト環境
     const response = await fetch('https://test.com.jp/ping');
     // 本番環境
     const response = await fetch('https://honban.com.jp/ping');

これを環境変数で指定した値にするためのメモです。

## 解決方法
ビルド時のsedコマンドで解決しました。
つまり、**単純な置換**です(力技だ……)。

## main.js

以下のように、`API_ENDPOINT_PLACEHOLDER`で置き換えます。
あとで「置換」するので、単に文字列です。
`${API_ENDPOINT_PLACEHOLDER}`とかではない、ということです。

```main.js
        const response = await fetch('https://API_ENDPOINT_PLACEHOLDER/ping');
        const response = await fetch('https://API_ENDPOINT_PLACEHOLDER/ping'); 
```

## dotenv(環境設定ファイル)
これは単に環境設定をしているテキストファイルです。
私のDockerでは、dotenvという名前にしていました。
これに、`DOMAIN`にURLを記述するものとします。

```text
DOMAIN=XXX.co.jp
```

## Dockerfile

以下の記述を足します。

```Dockerfile
# 環境変数を引数として受け取る
ARG DOMAIN

# sedコマンドでプレースホルダーを環境変数の値で置き換え
RUN sed -i "s|API_HOST_PLACEHOLDER|${DOMAIN}|g" ./static/scripts/main.js
```

環境設定ファイルは`env.txt`とか、任意の名前を付けて登録していると思います。
（この名前がスタンダード、というのがあればぜひ教えてください。）

## docker-compose.yaml

今回は`dotenv`として、docker-compose.yamlに記述しています。

```docker-compose.yaml
  sample-service: 
    build: 
      context: ./sample-service
    env_file:
      - dotenv
```

これに、`args`を書き加えます。

```docker-compose.yaml
  sample-service: 
    build: 
      context: ./sample-service
      args:
        - DOMAIN=${DOMAIN} 
    env_file:
      - dotenv
```

こうやってビルドすると、環境変数をソースに埋め込むことができます。
インスタンスを複数立てる時に役に立ちました。
python google translate

```py
# python -m pip install googletrans==3.1.0a0

from googletrans import Translator
import sys

args= sys.argv
if len(args) < 2:
    print('python3 translate.py 測試')
else:
    line = args[1]

    translator = Translator()
    translated = translator.translate(line, dest="zh-cn")
    
    print(line)
    print(translated.text)
    print()
    print('finished')
import pandas as pd
langdict = {0: {'zh-tw': '平安銀行'}}
df = pd.DataFrame(langdict).T
df['zh-cn'] = df['zh-tw'].apply(lambda x: translator.translate(x, src='auto', dest='zh-cn').text )
print(df)
```
iPhoneでNext.jsのlocalhostをデバッグしたい

# 概要
Macで開発中のNextjsの開発環境（localhost）をiPhoneで確認する方法の説明

<b>※ MacとiPhoneは同じネットワークに繋げる必要があります</b>

# 方法


## 手順1：ホストを指定してNextjsを起動

以下のようにhostnameを追加しておく
```json:package.json
  "scripts": {
    "dev": "next dev --hostname 0.0.0.0",
 ...
```

その後、Nextjsを立ち上げる
```bash:ターミナル
npm run dev


例
$ npm run dev                   

> test-app@0.1.0 dev
> next dev --hostname 0.0.0.0

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
```


## 手順2：MacのIPアドレスを調べる

「システム設定」＞「Wi-Fie」＞接続しているWifi名の「詳細...」をクリックして以下の「TCP / IP」画面を確認
赤枠で囲ったIPアドレスを覚えておく

![スクリーンショット 2024-03-14 12.27.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562718/74b4644a-0383-54c6-ca67-67833d27da0a.png)

## 手順３：iPhoneのブラウザで確認

同じWifiに繋いでいるiPhoneのブラウザで以下のURLを入力する
```
http://{手順２のIPアドレス}:{Nextjsを立ち上げているポート番号}

今回の例だとIPアドレスが「192.168.11.2」でNextjsの立っているポートが「3000」なので以下のURLになる
http://192.168.11.2:3000
```

以上でコード上で修正を加えた時もhot reloadが効いてリロードしなくても変更が反映されるようになる
マークダウンについて

知らなかった初見のものを記述してみる。

見出し　「#」+「半角スペース」+「見出しの文字」
リンク　[文章] +（link URL）
画像　　Gyazoなどで撮影後シェアをクリック→マークダウンをコピー


[![Image from Gyazo](https://i.gyazo.com/4094c4ab550a5ba7dfeefea1f1d3e7cb.png)](https://gyazo.com/4094c4ab550a5ba7dfeefea1f1d3e7cb)

[フリー素材お借りしました](https://www.pakutaso.com/20171002275iphone-16.html)


早速上記の技を使ってみましたができていそうな予感。
今回はgyazoでやってみましたが編集で余白のカットなど編集もできるのか気になります。
MacBook M1/M2/M3チップにImagemagickをインストールする方法（arm64オプション付き）

# MacBook M1/M2/M3チップにImagemagickをインストールする方法（arm64オプション付き）

最新のMacBookには、従来のIntelチップに代わってAppleが開発したM1/M2/M3チップが搭載されています。これにより、従来の方法ではなく、新しい手順でソフトウェアをインストールする必要があります。ここでは、MacBook M1/M2/M3チップにImagemagickをインストールする方法を紹介します。

## 1. Rosetta 2のインストール

まず最初に、Rosetta 2をインストールする必要があります。Rosetta 2は、IntelベースのアプリケーションをM1/M2/M3チップのMacで実行するための互換レイヤーです。ターミナルを開き、以下のコマンドを実行してRosetta 2をインストールします。

```bash
$ softwareupdate --install-rosetta
```

## 2. Homebrewのインストール

次に、Homebrewをインストールします。Homebrewは、Mac用のパッケージマネージャーであり、Imagemagickを含む多くのソフトウェアを簡単にインストールできます。

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

## 3. Xcode Command Line Toolsのインストール

Imagemagickをビルドするために、Xcode Command Line Toolsが必要です。ターミナルで以下のコマンドを実行してインストールします。

```bash
$ xcode-select --install
```

## 4. Imagemagickのインストール

Homebrewを使用してImagemagickをインストールします。

```bash
$ brew install imagemagick
```

## 5. 正常にインストールできたか確認

インストールが正常に完了したかどうかを確認するために、Imagemagickが正しくインストールされているかテストします。

```bash
$ magick --version
```

これで、MacBook M1/M2/M3チップにImagemagickが正常にインストールされ、使用できるようになりました。


## トラブルシューティング

### アーキテクチャの互換性の問題

エラーが発生する場合、以下の手順を確認してください。

> **エラー**: "Error: Cannot install on Intel processor under Rosetta 2 in ARM default prefix."


`arm64`アーキテクチャに関連するエラーがインストール時に発生した場合、HomebrewをRosetta 2のエミュレーションモードで実行しているためかもしれません。これを解決するには、以下のコマンドを実行します。
これはHomebrewを`arm64`モードで強制的に実行するコマンドで、MacBookのチップに互換性のあるImageMagickのバージョンをインストールします。

```bash
$ arch -arm64 brew install imagemagick
```

以上で、ImagemagickのMacBook M1/M2/M3チップへのインストール手順を紹介しました。問題が発生した場合は、公式のドキュメントやコミュニティフォーラムでサポートを受けることができます。

--- 

この手順を実行することで、MacBook M1/M2/M3チップ上でImagemagickを使用できるようになります。
GAS UTC → JST変換処理を記載して動かしたが変換されない。

## 概要

GASでスプレットシートで使う関数のUTCからJSTを定義したところなぜか変換が行われなかったので自分なりの解決策を簡単にまとめる。

## 内容

```js
function jst(utc = "2024/03/11 09:13:00") {
  console.log(utc);
  var jst = Utilities.formatDate(new Date(utc), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
  console.log(jst);
  return jst;
}
```

これだと下記のように出力される。

```
12:24:53	お知らせ	実行開始
12:24:53	情報	2024/03/11 09:13:00
12:24:53	情報	2024/03/11 09:13:00
12:24:53	お知らせ	実行完了
```

GASのスクリプトのタイムゾーンを東京から世界協定時刻に変更する。

![utcToJst_-_プロジェクトの設定_-_Apps_Script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/2ac92dd6-d627-0b2e-ca27-0630a7cbb3a2.png)
![utcToJst_-_プロジェクトの設定_-_Apps_Script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/87d16204-cba0-f5f2-6454-71bfa0b7f8df.png)

再度実行すると下記のように出力されたのでうまく変換できた模様

```
12:26:07	お知らせ	実行開始
12:26:07	情報	2024/03/11 09:13:00
12:26:07	情報	2024/03/11 18:13:00
12:26:07	お知らせ	実行完了
```
【ChatGPT有＋DALL-E3】で作品制作したあとはどうしてる？


　どうも、カーブミラーです。

　今回は、作品制作したあと、そのセッションはどうしてるのか、に焦点を当てます。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::
　まずは、
　　ニュース？

　X-Twitterで
　　話題になっている
　　　ロボットがいます。

　figure-1と呼ばれ、
　　MicrosoftとOpenAIが出資、
　　　ほかの投資家からも資金調達。

　そのfigure-1のビデオが公開されて
　　その動作が話題になりました。
　　　下記は、その動作の仕組みを
　　　　ビデオとともに
　　　　　説明したものです。
[figure-1](https://twitter.com/coreylynch/status/1767927194163331345?t=QI1bvavPAhjo5nu330Rj6A&s=19)

　このビデオのfigure-1には
　　ChatGPTアプリ版と思われる
　　　ものが組み込まれ、
　　　　人間と会話して、
　　　　　自分の前のものを認知して
　　　　　　人間に渡す、片付ける、
　　　　　　　を行なっています。

　確かに、
　　それ自体は
　　　よくできています。

　ですが、
　　ご存知のように
　　　アプリ版で会話していると
　　　　タイムラグがあって
　　　　　もどかしいですね。
　　　　　　それと同じことが
　　　　　　　ビデオにあります。

　つまり、
　　頭脳であるChatGPTが
　　　より高速になるか
　　　　何かしないと、
　　　　　研究段階から市場への
　　　　　　出荷にはなりえません。

　まぁ、いずれは
　　そうなるでしょうね。
　　　人間が求めているわけですから。
***
　世界シミュレーター“Sora”ですが、
　　OpenAIのCTOである
　　　Mura Muratiさんが
　　　　The Wall Street Journalの
　　　　　取材で明言しました。

　「Soraのリリースは
　　確実に年内で、
　　　数ヶ月以内かもしれない」と。

　確認は、
　　下記からどうぞ。
[X-Twitterの取材記事](https://twitter.com/WSJ/status/1767868286023160182?t=-9YUlEl6sKMC9NQw7U3acQ&s=19)
***
　さて、
　　本題です。

　今回は、
　　別に、無料版でも
　　　使えますので、
　　　　参考にしてください。

　作品制作したあと、
　　そのまま放っておいても
　　　構わないのですが、
　　　　イザというときに
　　　　　見つけられないことに
　　　　　　なります。

　見つかっても
　　それまでの時間が
　　　無駄です。

　もっと早く見つけたい、
　　みなさん、そう思いませんか？

　そこで
　　私のやり方を
　　　ご紹介しますので、
　　　　参考にしてみてください。
***
　まず、
　　作品制作を
　　　開始すると
　　　　セッション名が
　　　　　ChatGPTによって
　　　　　　付けられます。

　英語だったり
　　日本語だったり、
　　　ですよね。

　この機能は
　　ありがたくもあり、
　　　ありがたくもないものです。

　そこで
　　セッション名を
　　　おのれで書き換えましょう。

　この作業は
　　その時点でもOKですし
　　　ひと段落してからでも
　　　　構いません。

　次に、
　　その日の作業を終了したら
　　　翌日でも構わないので、
　　　　整理整頓します。

　このとき、
　　私はアプリ版を
　　　使って行ないます。

　理由は、
　　Web版だと
　　　セッション名を
　　　　変更すると
　　　　　トップに移動して
　　　　　　しまうからです。

　この点で
　　アプリ版は、
　　　変更しても移動しませんので、
　　　　ストレスがありません。

　整理整頓とは言いますが、
　　ここでも
　　　セッション名の変更をします。

　セッション名の先頭に
　　日付を追加するのです。

　これが
　　あとで効いてきます。

　画面上も
　　スッキリして
　　　見えますよw

　こんな感じに。
![Screenshot_20240314-112240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/7409b1e8-b160-962c-c5f4-c3131bb0c687.png)
***
　さて、
　　整理整頓が済みましたら、
　　　Web版に戻ります。

　この作業は
　　いつに行なうかは
　　　その人によって異なります。

　私の場合は
　　必要になったとき、かな。

　必要になったとき、それは、
　　そのセッションが
　　　必要になったときです。

　つまり、
　　必要になって、
　　　セッションを
　　　　探さねばならなくなる。

　どうやって探しますか？

　履歴を遡って？
　　大変ですよ？

　それよりも私は、
　　設定（Settings）の
　　　データ制御（Data Controls）タブ
　　　　エクスポート（Export）を
　　　　　使います。

　これを使って
　　履歴の圧縮ファイルを
　　　作成してもらって
　　　　ダウンロードします。

　そのファイルを
　　解凍しておく。

　そこに
　　“Chat.html”という
　　　ファイルがあります。
　　　　これが履歴の全文章に
　　　　　なります。
　　　　　　画像はありません。

　ところが
　　ずっとChatGPTに
　　　触っているので
　　　　内容が大量です。

　エディタで
　　開けないかもしれません。
　　　私は、非力なスマホなので
　　　　当然ながら開けません(泣)

　そこで
　　ブラウザで開くことを
　　　オススメします。
***
　ファイルを開いたら
　　目的のセッションを
　　　探します。

　ブラウザの
　　メインメニューから
　　　検索（ブラウザによって異なる）
　　　　をタップして、
　　　　　検索モードに。

　やり取りで使っていた文言、
　　例えば、“フィギュア”と入力して
　　　検索します。

　“フィギュア”が
　　使われている箇所が
　　　見つかります。

　必要なセッションを
　　見つけた、次は？

　ここで、
　　**セッション名の日付**が
　　　効いてきます。

　やり取りの
　　セッション名を確認して、
　　　Web版の履歴を
　　　　その日付までたどります。

　それで見つかれば、
　　それを使うとか、
　　　プロンプトを
　　　　コピるとかできます。

　もちろん、
　　そのセッションを
　　　続ける、という
　　　　選択肢もあります。

　そこは
　　用途によって、でしょう。
***
　これで
　　セッション名の変更、
　　整理整頓（日付）、
　　履歴の保存、
　　検索
　　　までの流れは
　　　　わかってもらえましたか？

　この記事が
　　みなさんの
　　　作品制作の糧に
　　　　なれば、幸いです。

　今日は、ここまで。
Linuxでのリモート接続先をシンボリックリンク作成

### リモート接続先のデータ保存場所

下記のフォルダに保存される。
```/run/user/100X/gvfs/ftp:host=IPアドレス/フォルダ階層```

### リンクを作成

ターミナルでリンクを作成したいディレクトリへ行き、下記コマンドを実行する。
ここでのファイル名は、上記の場所を入力する。

```
ln -s ファイル名 リンク名
```
plot stock graph

```py
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import json
from datetime import datetime, timedelta
from data import GetData

symbol = "AAPL"
def GenerateGraph(params):
    data = {}
    data_needed = ["Date", 'Open', "High", "Low", "Close"]

    price_data = GetData(symbol)
    for col in data_needed:
        data[col] = [i[col] for i in price_data]

    layout = go.Layout(
        xaxis = go.layout.XAxis(
            showticklabels=False),
        yaxis = go.layout.YAxis(
            showticklabels = False
        )
    )

    fig = go.Figure(data=[go.Candlestick(x=np.arange(0, len(data['da'])),
                    open=data["Open"],
                    high=data["High"],
                    low=data["Low"],
                    close=data['Close'])], layout=layout)

    fig.update_layout(xaxis_rangeslider_visible=False)
    fig.add_annotation(x=len(data["da"]), y=data['cl'][-1]*1.01, text=data['cl'][-1])
    fig.write_image(f"{symbol}.png")
    # fig.show()
```
Ruby on Railsでコントローラー名と紐づいているもの

コントローラー名をBooks→Testに変える場合

### routes.rbにて名称変更
/kakeibo/config/routes.rbを下記の通り変更する。

get "/books", to: "books#index"
↓
get "/books", to: "test#index"

### コントローラーファイルの名前を変更

/kakeibo/app/controllers/books_controller.rb
↓
/kakeibo/app/controllers/test_controller.rb

### ファイル内のコントローラー名を変更する
/kakeibo/app/controllers/books_controller.rbを下記の通り変更する。

class BooksController < ApplicationController
↓
class TestController < ApplicationController

### viewsのフォルダ名を変更

/kakeibo/app/views/books
↓
/kakeibo/app/views/test

### 全部変更した後にサーバーを立ち上げなおす

```
$ rails s
```

### 参考
下記サイトにて変更に必要な作業が書いてある。

https://qiita.com/naretora/items/5b628b42d1ff4eba3602
vue + pug

# vscode + vue 単一コンポーネント + pugでの補完
vscode extentions 'Vue - Official'をインストール
yarn add -D @vue/language-plugin-pug

```tsconfig.json
{
  "compilerOptions": {...},
  "vueCompilerOptions": {
    "plugins": ["@vue/language-plugin-pug"]
  },
  ...
}
```

@volar/vue-language-plugin-pug は非推奨になったみたい
ランキングでPythonで表現する手法


## 大体に共通すること

df.sort_values()で成績順に並び替える


## 表で表現

https://dodotechno.com/python-make-ranking/


グラフで表現

グラフで表現したい際はこちら；


ランキングチャート


https://qiita.com/toyohisa/items/8b659457378dd7df3a35

### ヒストグラム

一般的な棒グラフ。

https://www.sejuku.net/blog/71148





### 積み上げ棒グラフ


平均値を出してランキングにしたい

具体的なコード
~~~
User
vlookup的な機能はPythonにありますか？エクセルシートのデータをベースに事例を書いてください。　A列のデータの種類を参考に、B列に様々あるデータポイントの平均値を行ごとに出して、A列のデータ種類ごとに平均を最終的に一つにして上位２０と下位２０このA列データのランキング形式でヒストグラム表示をしてほしいです。
ChatGPT
Pythonでは、pandasライブラリを使用してVLOOKUPに相当する機能を実装することができます。以下に、エクセルシートのデータをベースにしたPythonコードを示します。

python
Copy code
import pandas as pd

# エクセルファイルを読み込む
excel_file_path = "your_excel_file.xlsx"
df = pd.read_excel(excel_file_path)

# A列のデータの種類ごとにB列のデータポイントの平均値を計算
average_values = df.groupby('A列').agg({'B列': 'mean'})

# A列のデータの種類ごとに平均値を最終的に一つにしてランキング形式で表示
ranked_values = average_values.rank(method='min', ascending=False)

# 上位20と下位20のデータを取得
top_20 = ranked_values[ranked_values <= 20].dropna()
bottom_20 = ranked_values[ranked_values > len(ranked_values) - 20].dropna()

# ヒストグラム表示
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.hist([top_20.values.flatten(), bottom_20.values.flatten()], bins=20, label=['Top 20', 'Bottom 20'])
plt.xlabel('Rank')
plt.ylabel('Frequency')
plt.title('Top 20 and Bottom 20 A列データのランキング')
plt.legend()
plt.show()
~~~

このコードでは、pandasライブラリを使用してエクセルファイルを読み込み、A列のデータの種類ごとにB列のデータポイントの平均値を計算します。次に、平均値をランキング形式で表示し、上位20と下位20のデータを抽出しています。最後に、matplotlibライブラリを使用してヒストグラムを作成し、上位20と下位20のA列データのランキングを表示しています。


### ranked_values = average_values.rank(method='min', ascending=False)では何をしているか

ranked_values = average_values.rank(method='min', ascending=False)という行は、pandasのrank()メソッドを使用して、各グループの平均値をランキングするためのものです。

具体的には、average_valuesはA列のデータの種類ごとにB列のデータポイントの平均値が格納されたDataFrameです。rank()メソッドは、この平均値のランキングを計算し、新しいDataFrameを返します。method='min'は同じ値が複数ある場合に最小ランクを適用することを意味し、ascending=Falseは降順でランキングすることを指定しています。

つまり、この行はA列のデータの種類ごとにB列のデータポイントの平均値をランキングしており、その結果をranked_valuesという変数に格納しています。ランキングの基準は、各平均値が高いほどランクが低くなります。




# ヒストグラム豆知識

## bins

Matplotlib はデータをプロットするためのライブラリです。 ヒストグラムでは、値の範囲を複数指定し、それぞれの範囲に入っているサンプルの個数を描画します。 そのため、その値の範囲の指定を bins という引数を用いて行う必要があります。 
bins はオプショナルな引数で、何も与えなかった場合はビンの数が自動的に決定されます。 
ヒストグラムは、量的データの分布の様子を見るのに用いられます。 データをいくつかの階級に分け、度数分布表を作成してからグラフを作成します。 横軸にデータの階級を、縦軸にその階級に含まれるデータの数（人数、個数など）をとります。 
ヒストグラムは、柱状図、柱状グラフ、度数分布図とも呼ばれます。
`bokeh.plotting.figure.text()`関数の`text`引数にlist型でなくstr型の値を渡すと、グラフに文字列が表示されない

# 環境
* Python 3.12.1
* bokeh 3.0.3

# やりたいこと
bokehを使って、`(x,y)=(1,2)`の場所に点と文字列を表示したいです。
以下のPythonファイルを実行しました。

```python:sample.py
from bokeh.io import output_file, save
from bokeh.plotting import figure

fig = figure(width=300, height=300)
fig.circle(x=1, y=2)
fig.text(x=1, y=2, text="foo")

output_file("output.html")
save(fig)
```

# 何が起きたか
`output.html`をブラウザで開くと、`(x,y)=(1,2)`の場所に点は表示されましたが、文字列`foo`は表示されませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37903/7874294e-1eac-99c5-f0e5-92fdc9d14353.png)

# 原因と解決策
上記のPythonファイルを、bokeh 3.3.4（2024/03/14時点で最新バージョン）を利用して実行すると、以下のエラーメッセージが出力されました。

```
$ python sample.py
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name. This could either be due to a misspelling or typo, or due to an expected column being missing. : text='foo' [no close matches] {renderer: GlyphRenderer(id='p1048', ...)}
```

`foo`という列を探そうとしたけど見つからなかったので、グラフに文字列`foo`は表示されなかったようです。

`text`関数の`text`引数に、文字列ではなくlistを渡せば、グラフに文字列`foo`は表示されました。

```python
# fig.text(x=1, y=2, text="foo")
fig.text(x=1, y=2, text=["foo"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37903/4a448033-8be9-0592-1bae-0308eca3bf8e.png)

引数`x`, `y`にはlist型の値を渡さなくても問題ないようです。


ちなみに、`text()`関数のリファレンスを確認しましたが、`text`引数の値が文字列のときとlistのときで、どう挙動が変わるのかは記載されていませんでした。

https://docs.bokeh.org/en/latest/docs/reference/plotting/figure.html#bokeh.plotting.figure.text

>text (StringSpec, optional) – The text values to render. (default: Field(field=’text’, transform=Unspecified, units=Unspecified))
Docker Composeを用いてローカルでECRイメージのトラブルシューティングを行う

## はじめに

Amazon Elastic Container Service（ECS）でコンテナ起動問題に直面した際には、ローカル環境でのトラブルシューティングが有効です。この記事では、AWS Elastic Container Registry（ECR）からイメージを取得し、ローカルで実行することで問題解決へのアプローチを紹介します

## 手順

### AWS CLIを用いてECRからイメージをプルする

まず、AWS CLIを通じてECRからDockerイメージをプルします。これには、適切な権限を持つIAMユーザーが必要です。以下のコマンドを実行し、ECRにログインし、イメージをローカルにプルします

```bash
aws ecr get-login-password \
	--region リージョン名 \
	| docker login \
			--username AWS \
			--password-stdin アカウントID.dkr.ecr.リージョン名.amazonaws.com \
			docker pull アカウントID.dkr.ecr.リージョン名.amazonaws.com/リポジトリ名:タグ
```

### ローカルでDockerコンテナを実行する

次に、プルしたイメージを使用してローカルでDockerコンテナを実行します。ここでの課題は、コンテナが依存する他のサービスやデータベースへの接続設定です

```bash
docker run --rm -it --network=プロジェクト名_default \
	-e DB_HOST=データベースサービス名 \
	-e DB_PORT=ポート番号 \
	-e DB_USER=ユーザー名 \
	-e DB_PASS=パスワード \
	イメージ名
```

### Docker Composeで環境を構築する

複数のサービスやネットワーク設定が必要な場合、Docker Composeを用いて環境全体を定義し、管理します。**`docker-compose.yml`** ファイルを作成し、必要なサービス、ネットワーク、ボリュームを定義します。

```yaml
version: "3.8"
services:
  app:
    image: イメージ名
    ports:
      - "外部公開ポート:コンテナ内ポート"
    networks:
      - default
    depends_on:
      - database

  database:
    image: データベースイメージ名
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=パスワード

networks:
  default:
    driver: bridge
```

### トラブルシューティング

コンテナが正常に起動しない場合、ログを確認し、設定や依存関係に問題がないかを確認します。**`docker logs コンテナID`** コマンドでコンテナのログを確認できます

```jsx
docker run --rm -it --network=_default \
	-e DB_HOST=mysql \
	-e DB_PORT=3306 \
	-e DB_USER=root \
	-e DB_PASS=root \
	アカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/イメージ名 sh
```

## まとめ

ローカル環境でのトラブルシューティングは、クラウド環境で発生する問題を効率的に解決するための強力な手段です。Docker Composeを使用することで、本番環境と同じ条件をローカルで再現し、問題の原因を特定しやすくなります
n8nセットアップ時に Request failed with status code 401 が表示されてセットアップできない問題への対応

HTTPなローカル環境でn8nをセットアップしようとすると、以下のように「Request failed with status code 401」というメッセージが表示され、セットアップを進められない問題が発生します。（n8n 1.1.1およびそれ以降のバージョンで発生します）

![スクリーンショット 2024-03-14 10.32.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3fa9ff12-d3f8-9490-cad8-6782e1201ca9.png)


# 対応方法
Dockerでn8nを実行する場合は、以下のコマンドを実行します。

```shell
# docker run -it --rm --name n8n -e N8N_SECURE_COOKIE=false -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
```

なお、Docker以外でも、 `N8N_SECURE_COOKIE` 環境変数を `false` に変更することで、同様に対応可能です。

# 参考情報

https://community.n8n.io/t/problem-setting-up-owner-401/16085/4
【スクラム】Q.Problemと妨害リスト（インペディメントリスト）はどう使い分ければ良いか

駆け出しスクラムチームからよく聞かれる質問への回答。
※スクラムの実務経験がない個人の私見です

## 質問内容
Problemと妨害リストの違いがわからない。
どう使い分ければ良いか。

### 前提
- レトロスペクティブで振り返りのフレームワークとしてKPTを使っている

## 私の回答
### 妨害リストについて
妨害リストでは、そのスプリントに関わらず、またスプリントゴール達成に関係がなくとも、困っていることを管理します。
外的要因が絡んでくることが多く、また即時解決が難しく長期的に解決を目指していくものも出てきます。

**妨害リストの例**
- PJ以外の割り込みタスクが多い
- POが多忙で受け入れ確認をスプリント終盤まで進められないことが多い
- スクラムチームのスクラム理解度が浅く、各イベントが効果的に機能しない（タイムボックスが守られなかったり、レトロで改善が出なかったり）
- ステークホルダーの声が強く、POの意見が通らない
- フロントの実装がAさんに依存している

### KPTについて
レトロスペクティブでは主に**そのスプリントにおいてスプリントゴール達成のための行動の中で**、うまくいかなかったこと、改善できそうなことについて振り返ります。
基本、自分達の行動改善だけで解決できるものになってくると思います。


**Problemの例**
- 進捗が芳しくないことにスプリント終盤で気づいた
- PBIがReadyでなかった（スプリント中にPOやステークホルダーへの確認で待ちになるものが多かった）
- バッファを考慮していたはずが、PBIの完了だけで手一杯だった
- 共有や相談をデイリーまで待つケースが多かった

話がそれますが、KPTでよく見かけるアンチパターンについて。

- **Problemに原因まで記載する**
Problemに原因まで書く人が結構いますが、事象までで留めることをお勧めします。最初から原因が書いてあると、その原因の解消のみにフォーカスされがちですが、その事象が起きた原因はそれだけじゃないかも知れず、もしかしたら他の原因の方がクリティカルかも知れません。
- **Tryに行動改善でなくタスクが上がっている**
解決策がタスク（〜〜リストを作成する、Wikiに〜〜について記載する、など）であればKPTで管理するのではなく、PBIを作ってしまいましょう。

### 最後に
Problemや妨害リストの定義を気にしすぎて問題点・課題の検知漏れがあると本末転倒なので、一旦Problemとしてはあまり深く考えず色々上げた上で、適切な管理先（ProblemなのかPBIなのか妨害リストなのか）へ移動させれば良いかと思います。
実例で理解する【Docker 後編】

# はじめに

前編はこちら

https://qiita.com/kohki_takatama/items/3ffd45f31dbe8acd4749

後編はDockerfileについてです。
Dockerfileはこだわった点は少なく、むしろ通例らしきものをコピペした部分が多いです。
# `Dockerfile`

```Dockerfile
FROM ruby:3.1.4
RUN apt-get update -qq
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
RUN npm install --global yarn

WORKDIR /linebot
RUN gem install bundler:2.3.17
COPY Gemfile Gemfile.lock /linebot/
RUN bundle install
```

## イメージの指定

```Dockerfile
FROM ruby:3.1.4
```

イメージ（コンテナの設計図）を指定しています。
今回はRuby公式の、`3.1.4`タグ（バージョン）を使用します。
ここでの数字（3.1.4）はDocker hubにおけるバージョンを指し、同時にRubyそのもののバージョンでもあります。
Docker hubにおけるタグは、その中身のバージョンと合わせるのが一般的です。

## ソフトとツールのインストール

```Dockerfile
RUN apt-get update -qq
```

- `apt-get`
Ubuntuにおいて、インストール / アップデート / 削除に使用するコマンドです
OSによって変わり、例えばmacでは`brew`（公式ではないですが）、windowsでは`winget`が使用されます。
- `-qq`オプション
`-q（quietモード）`をさらに「静かに」するコマンドです。具体的には、進捗の表示を行わず、エラーのみを表示します。

```Dockerfile
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
```

- `curl`
URLにアクセスし、コンテンツを取得するコマンドです。今回は`node.js`のインストールに使用します。
- `-fsSL`オプション
簡単に言うと「エラー以外を表示しない」モードです。具体的には、以下です。
    - `f`：fail エラーメッセージを返す
    - `s`：silent 進捗を表示しない
    - `S`：Show-error エラーは表示する
    - `L`：Location アクセスしたURLがリダイレクトを指示してきたとき、それに従う
- URLについて
今回は「長期サポート版（LTS）の`node.js`をセットアップするスクリプト」のURLにアクセスしています。
- `| bash -`
`|`は「パイプ」と呼ばれます。前のコマンドの結果（今回は`node.js`のセットアップスクリプト）を、次のコマンド（`bash`）の引数として渡しています。
`-`は、標準入力からスクリプトを受け取ることを示します。今回は「前のコマンドの出力をスクリプトとして受け取る」ことを明示しています。`-`は無くても動作するかもしれません。未検証です。
- `install -y nodejs`
`node.js`のインストール時にはいろいろ聞かれるのですが、その全てに自動的に`yes`と答えます（`-y`オプション）

`install -y nodejs`

```Dockerfile
RUN npm install --global yarn
```

`yarn`というパッケージマネージャーをインストールしています。
`--global`オプションは、特定のプロジェクトだけでなく、システム全体でインストールしたものを使用できるようにします。
曖昧なイメージになりますが、`Rails`は`yarn`を採用しているため、このインストールは必須だと思います。
（`node.js`にはデフォルトのパッケージマネージャー`npm`があるため、通常は`yarn`のインストールは必須ではない）

https://jp.quora.com/Rails%E3%81%AFYarn%E3%82%92%E6%8E%A1%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%81%8C%E3%81%AA%E3%81%9C%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B-Node%E3%82%92%E4%BD%BF%E3%81%86%E3%81%AE%E3%81%A7npm

## ディレクトリの作成

```Dockerfile
WORKDIR /linebot
RUN gem install bundler:2.3.17
COPY Gemfile Gemfile.lock /linebot/
RUN bundle install
```

`WORKDIR /linebot`で、コンテナ内に`linebot`というディレクトリを作成し、作業ディレクトリを`linebot`に移動しています。

そこにbundler（gem管理ツール）をインストールしていますね。gemの依存関係がよくわからないのでインストールして丸投げしよう、という思考だったのですが、これは必要なかったかも？
まあ、bundlerがあって損することはないかな。

その後、ローカルにあるGemfileをコピーし、`bundle install`を行っています。GemfileにはRailsのみ記載しており、ここではRailsのインストールを行っています。
# おわりに

記事にしてみると不要なところも多かったような・・・

気力があれば再考します。
Mozcのデフォルト入力をひらがなにする

ソースからrebuildする
```bash
 sudo apt install build-essential devscripts -y
 sudo apt build-dep ibus-mozc -y
 apt source ibus-mozc
 ```

 方法二つがあります
 
 方法1.CompositionMode修正
```./mozc*/src/protocol/commands.proto ```を編集して、
```
enum CompositionMode {
    DIRECT = 0;
    HIRAGANA = 1;
```
 の部分を
```
enum CompositionMode {
    DIRECT = 1;
    HIRAGANA = 0;
```
 のように変更します。


  方法2.kActivatedOnLaunch
```cd ~```
``` ./mozc*/src/unix/ibus/property_handler.cc```を編集します。

```
     #if IBUS_CHECK_VERSION(1, 5, 0)
     const bool kActivatedOnLaunch = false;
```
 の部分を
```
    #if IBUS_CHECK_VERSION(1, 5, 0)
    const bool kActivatedOnLaunch = true;
```
のように変更します。


  次はbuild
```bash
cd mozc*
dpkg-buildpackage -us -uc -b
```

```sudo apt install ./ibus-mozc*.deb (dfsg version)```

そして再起動して完成。
[論文読み] Detecting Deepfakes with Self-Blended Images


今回，紹介する論文である「Detecting Deepfakes with Self-Blended Images」は東京大学の山崎研究室が提案した手法である．

# 概要
Self-Blended Images(SBIs)は学習時に実際のDeepfake画像を必要としない自己教師あり学習ベースの手法である．
Face X-RayやPCL-I2Gは2枚のReal画像から疑似的なDeepfake画像を生成していたがSBIsでは，1枚のReal画像から疑似的なDeepfake画像を生成する生成器とDeepfakeとRealの2クラスを予測するモデルで構成される．

# アプローチ
SBIsは，1枚のReal画像に微小な変化を加えて疑似的なDeepfake画像を生成することで微細な偽造痕跡を表現できるという点に着目している．

## Self-Blended Images(SBIs)
SBIsは1枚のReal画像から疑似的なDeepfake画像とラベルを生成する．

![sbis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744226/7314c159-ebcc-1117-808b-d6207e7849e3.png)

SBIsは3つの手順で疑似的なDeepfake画像とラベルを生成する．

### 1，ソース画像とターゲット画像の生成
元画像$I$をSource-Target Generator(STG)とMask Generator(MG)に入力する．STGでは元画像$I$をData Augmentationによりソース画像$I_s$とターゲット画像$I_t$に拡張する．また，ソース画像に平行移動とサイズ変更を行うことでDeepfakeの偽造痕跡を再現している．

### 2，マスクの生成
MGでは元画像$I$から顔の器官点を推定し，1で移動した位置に合わせて器官点からソース画像$I_s$とターゲット画像$I_t$を合成するマスク$M$を生成する．生成するマスク$M$は，ターゲット画像$I_t$に対してソース画像$I_s$の合成領域を指定するものである．

### 3，合成
下記の式に従いターゲット画像$I_t$とソース画像$I_s$，生成したマスク$M$を用いてDeepfake画像$I_{SB}$を生成する．

```math
\begin{align}
    {I}_{SB} = {I}_{s}\odot M+{I}_{t}\odot(1-M)
\end{align}
```

## モデル
モデルは，Real画像とSBIsで生成した疑似的なDeepfake画像とラベルを用いて学習を行う．
モデルにはImageNetで学習済みのEfficientNet-B4を用いている．

## 損失関数
損失関数は予測クラスと正解ラベルとのクロスエントロピーで定義される．

# 実験
いくつかの実験を抜粋して結果を記載する．
Area Under Curve(AUC)で比較する．

## 実験1，FF++に対するAUC比較
Face X-RayとPCL-I2G，SBIsで生成した疑似的なDeepfake画像で学習したEfficientNet-B4のFF++に対するAUCを比較する．
どのモデルも非常に高いAUCであるがなかでもSBIsで学習したEfficientNet-B4は最も高いAUCである．

![result7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744226/483496c1-e188-1523-0f7a-1f93bf3fbfd2.png)

Real画像(上段)とSBIsで生成した疑似的なDeepfake画像(下段)の比較．
Real画像との差がほとんどないことが分かる．

![sample_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744226/e6d31106-b07e-6d12-c119-7618c32c62a3.png)

## 実験2，汎化性能の評価
FF++やFF++で生成した疑似的なDeepfake画像で学習した従来手法とSBIsで生成した疑似的なDeepfake画像で学習したEfficientNet-B4のCDF，DFD，DFDC，DFDCP，FFIWに対するAUCを比較する．
SBIsで生成した疑似的なDeepfake画像で学習したEfficientNet-B4はほぼ全てのデータセットにおいて最も高いAUCを達成している．

![result6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744226/f34f4ce9-a30d-7cf7-9980-42eef184e980.png)

# まとめ
SBIsは1枚のReal画像から疑似的なDeepfake画像を生成するSBIsとDeepfakeとRealの2クラスを予測するモデルで構成される手法である．
1枚のReal画像から疑似的なDeepfake画像を生成し学習に用いることで頑健なDeepfake検出が可能である．

# 参考文献
論文：Detecting Deepfakes with Self-Blended Images
LINK：https://arxiv.org/abs/2204.08376

# 備考
・公式の実装
https://github.com/mapooon/SelfBlendedImages
・非公式の実装
なし
Segmentation Models on Pytorchを動かしてみる：①CUDA-GPU環境の設定

# セマンティックセグメンテーション
画像解析による物体認識の一手法として，セマンティックセグメンテーションというものがあります．これは，画像において物体にラベルを付けて，元画像とラベル化画像を使ってモデルを学習させ，ピクセル単位で画像からラベル（つまり物体）を予測しようとするAI手法です（たぶん）．

これを使って河川に浮遊する物質動態を把握しようと考え，Python環境のPytorchで動く[Segmentation Models](https://github.com/qubvel/segmentation_models.pytorch)を動かした際の注意点について忘備録的にまとめてみます．

なお，著者は画像解析については素人同然なのでそのつもりでお読みください．

今回試したPC環境については以下です．

OS：Windows 10
GPU：NVIDIA RTX A6000

また，Pythonについては，Anaconda 3のJupyternotebookで動かします．

# CUDA-GPU環境の構築
上記Segmentation ModelsにおいてあるコードはCPU環境でも動きますが，CUDA-GPUを導入したほうが計算は断然速いです．ただし，設定には若干の手間がかかります．

基本的に下記ページの手法を参照します．

https://frqux.hatenablog.com/entry/2023/02/07/062433

# Pytorchのインストール

Anaconda Promptよりインストールを行いますので，コマンドを以下から確認します．

https://pytorch.org/get-started/locally/

ここでは，

PyTorch Build　→　Stable (2.2.1)
OS　→　Windows
Pakage　→　Pip
Language　→　Python
Compute Platform　→　CUDA 11.8

とします．CUDAは12.1も使えそうですが，最新版は必ずしもほかが対応しているとは限らないので一つ古いものを選択しています．

これによりコマンドは以下となりました．

pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

これをAnaconda Prompt（単にWindowsスタートメニューのAnaconda3内にあるAnaconda Promptでよい）に入力してインストールします．

※単にpip install torch torchvision torchaudioとすると，CUDAを使えないので注意．著者は最初これでだいぶはまり込みました．．

インストールが終わるまで少々（私の場合数分）待ちます．

# CUDA Toolkitのインストール

下記ページより，適切なバージョンをインストールします．

https://developer.nvidia.com/cuda-toolkit-archive

バージョンは先ほどPytorchのところで指定したCUDA11.8を選択し，自分のOSにあったものを選びます．Installer Typeはexe(local)を選択しました．

ダウンロードが終わったら，exeを実行します．特にそのままのインストールで問題ないと思います．

# NVIDIAドライバのインストール

使用しているGPUに対応したNVIDIAドライバを以下からダウンロードします．

https://www.nvidia.co.jp/Download/index.aspx?lang=jp

ここでの環境ですと，以下のような感じです．

製品のタイプ　→　NVIDIA RTX/Quadro
製品シリーズ　→　NVIDIA RTX Series
製品ファミリー　→　NVIDIA RTX A6000
オペレーティングシステム　→　Windows 10 64bit
ダウンロードタイプ　→　製品ブランチ/studio
言語：Japanese

こちらも普通にダウンロード→exe実行でインストールします．途中画面が暗くなったりします．

インストール後，再起動を求められますので，PCを再起動します．

# 確認

Jupyternotebookで以下を試してみます．

```Python:
import torch
print(torch.cuda.is_available())
```

うまくいっていると，Trueと返してくるはずです．

# あとがき

これでCUDA-GPU環境については整いました．[次の記事](https://qiita.com/champon487/items/b2a4f3bfa596ae75934a)では実際にSegmentation Modelsを動かしてみます．

※以前試したときは，cnDNNなどのインストールも必要だったような．．？？

https://developer.nvidia.com/cudnn-downloads
AWS勉強備忘録6 - EC2の設定手順

AWSのEC2を利用するには、複数の設定ステップを経る必要があります。本記事では、EC2インスタンスの立ち上げから、セキュリティ設定、ソフトウェアのインストールまでの手順を詳細に解説します。

## 1. AWSにログインし、準備する

- **AWSにログイン**: AWSマネジメントコンソールにアクセスしてログインします。
- **リージョンの選択**: 利用するリージョンを選択します。リージョンによって利用できるサービスやインスタンスタイプに違いがあるため、プロジェクトのニーズに合ったリージョンを選択しましょう。
- **EC2ダッシュボードの開始**: マネジメントコンソールから「EC2」を検索し、ダッシュボードを開きます。

## 2. EC2インスタンスを作成する

### AMIの選択
Amazon Machine Image（AMI）を選択します。AMIは、インスタンスのテンプレートとなるもので、OSやプリインストールされたソフトウェアを含みます。

### インスタンスタイプの選択
必要なCPU、メモリ、ストレージの種類に合わせてインスタンスタイプを選択します。用途に応じて、最適なインスタンスタイプを選定しましょう。

### ネットワーク設定とIPアドレスの割り当て
VPC（Virtual Private Cloud）を選択し、サブネットを設定します。また、インスタンスにはデフォルトでプライベートIPが割り振られますが、外部との通信が必要な場合はパブリックIPの割り当ても行います（※要確認）。

### ストレージの追加
必要に応じてEBS（Elastic Block Store）などの追加ストレージを設定します。データの永続性やI/Oパフォーマンスに応じたストレージタイプを選択しましょう。

### セキュリティグループの設定
インスタンスへのアクセスを制御するセキュリティグループを設定します。セキュリティグループは、特定のポートへのアクセスを許可または拒否するルールを設定することで、インスタンスのセキュリティを強化します。必要な通信のみを許可するように細かく設定しましょう。

### キーペアの選択（または作成）
インスタンスへのSSH接続に必要なキーペアを選択します。まだキーペアを持っていない場合は、新しく作成することができます。キーペアはインスタンスに安全にアクセスするために必須ですので、紛失しないように注意しましょう。

## 3. EC2インスタンスに接続する

インスタンスが起動したら、SSHを使用してEC2インスタンスに接続します。接続には、前段階で設定したキーペアが必要になります。ターミナルまたはコマンドプロンプトから、AWSが提供する接続情報を使ってインスタンスに接続しましょう。

## 4. ソフトウェアのインストールや設定を行う

インスタンスに接続できたら、必要に応じてソフトウェアをインストールし、アプリケーションの設定を行います。これには、Webサーバーの設定、データベースのインストール、アプリケーション固有の設定などが含まれます。

## インスタンスの設定項目について

EC2インスタンスを設定する際には、以下の項目に特に注意が必要です。

- **AMI**: インスタンスのOSや初期ソフトウェア環境を決定します。
- **インスタンスタイプ**: CPU、メモリ、ストレージの性能を決定します。
- **リージョンとAZ（アベイラビリティゾーン）**: データセンターの物理的な場所を決定し、可用性とレイテンシーを最適化します。
- **VPCとサブネット**: インスタンスのネットワーク環境を設定します。
- **IAMロール**: AWSリソースへのアクセス権をインスタンスに割り当てます。
- **ストレージ**: EBSなどの追加ストレージの容量と種類を選択します。
- **セキュリティグループ**: インスタンスへのアクセスを制御するルールを設定します。

プライベートIPアドレスは、VPC内でインスタンスが通信するために割り当てられます。外部インターネットとの通信が必要な場合は、パブリックIPアドレスを割り当てるか、NATゲートウェイを使用する必要があります。

以上が、AWSのEC2を設定するための基本的なステップと重要な設定項目です。これらのステップに従って、セキュアでパフォーマンスの高いEC2インスタンスを設定し、アプリケーションの運用を始めましょう。
【googleスライド】画像を丸く切り抜く


# はじめに
googleスライドで画像を丸く切り抜きたい時があった。
いつもの癖で編集からマスクを探していたが、そもそも切り抜く機能があった！

### 画像を貼る
![スクリーンショット 2024-03-14 9.28.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587166/91d4dafd-cae6-1bf5-69e2-9c302133a6b7.png)

### 丸くする
上のツールバーからスクショのボタンを押して好きな形を選ぶ
![スクリーンショット 2024-03-14 9.31.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587166/220404eb-56fb-4c56-e067-e76ddc7bea8b.png)

###　丸くなる
![スクリーンショット 2024-03-14 9.34.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587166/32e11ab1-4bad-3eb6-f49a-ca0d42aa3453.png)

これだけ！
Zoomで保存されたレコードデータをC#で取得したい

そもそもやりたいことは自動で、zoomでクラウド記録された音声をAzureにコピーして、文書化したいのです。

zoomのアクセストークンが従来のJWTが廃止されるというので話がややこしい

:::note warn
JWTアプリタイプは、2023年6月に非推奨になります。アカウントのJWTアプリの機能を置き換えるために、サーバー間OAuthまたはOAuthアプリを作成することをお勧めします。
:::
まずはここが第一関門になりそうです

サーバー間OAuthアプリを作成しないといけないのでまずはここから
https://marketplace.zoom.us/docs/guides/build/server-to-server-oauth-app/#create-a-server-to-server-oauth-app--omit-in-toc-

## 権限を有効にする
で、管理者じゃないとだめとか、開発モードの編集許可とかがあるのですが
そのあたりの設定は、所有者「オーナー」の権限でないと
で、サーバー間OAuthアプリの権限は、管理者は初期値では許可されていないのでそれをオンにする必要があります。
zoomの手順書では
https://marketplace.zoom.us/docs/guides/build/server-to-server-oauth-app/#enable-permissions
[ユーザー管理] > [役割] >[役割設定] >[詳細機能]に移動し、サーバー間OAuthアプリの[表示]チェックボックスと[編集]チェックボックスをオンにします。
という感じですが
細かく言えば
[ユーザー管理] > [役割] >**[管理者を選択]**>[役割設定] >[詳細機能]に移動し、サーバー間OAuthアプリの[表示]チェックボックスと[編集]チェックボックスをオンにします。

## サーバー間OAuthアプリを作成する
https://marketplace.zoom.us/docs/guides/build/server-to-server-oauth-app/#create-a-server-to-server-oauth-app

Auth2でトークンを取得する

POST https://zoom.us/oauth/token?grant_type=account_credentials&account_id={accountId} 
HTTP/1.1
Host: zoom.us
Authorization: Basic Base64Encoder(clientId:clientSecret)

で、取得する
Basic認証で取得する

Authorizationヘッダで送る
プログラムからBASIC認証がかけられたURLにアクセスする場合にはAuthorizationヘッダーにユーザ名、パスワードをセットしてリクエストする。

ユーザ名、パスワードは:(コロン)でつなぎ、BASE64でエンコードして、ヘッダ全体では次のようになるようにする。

Authorization: Basic <BASE64エンコードしたユーザ名:パスワード>

って、事

.net的には
WebClientは非推奨？らしいのでHttpClientを使う
6年間事業会社で働いた今だから思える、あの頃の自分につたえたいこと

## はじめに
2018年4月に新卒入社してから時間があっという間に過ぎて、来月から7年目になります。
ここには、自分が6年間の中で過去の自分に伝えたいことを残したいと思います。

## キャリアが真っ白で不安になっているキミへ
自分がIT業界で働こうと思ったきっかけは本当になんとなくで。
「手に職がほしいな」「オンラインゲームしていたからタイピングはそこそこできる」「今後生きていく中でPCが使えて困ることなんてないだろうな」なんて理由で情報系の道へ進んだ自分。

いざ社会人になって、自分のキャリアを改めて考えると、なんとなくでこの道を選んでしまったもんだから10年後、20年後を思い描けなくて不安だったと思う。

大丈夫。社会人になりたてだから不安なんじゃない、きっとその不安は今後もずっとそばにいる笑
今すぐに10年後のことを今決める必要はない。でも、「1年後はこんなふうになりたい」「◯◯先輩の働き方かっこいいからこの人に近づきたい」「後輩が入ってきたら頼ってもらえるようになりたい」とか少し先の未来のことはイメージしてほしい。
油断すると、なんとなく仕事をして1年無駄にしてしまったなと感じてしまうかもしれないので、小さな目標は持ち続けてほしい。6年間働いた今なら言えるけど、昔よりも10年後の自分がイメージしやすくなった気がする。（気がする）

## 技術者として自分の存在価値に不安を持ちはじめているキミへ
うーん、これも6年後に解決しているかと言われるとなんともいえない内容。
会社のプロジェクトとしていろいろな技術に触れられて、メンバー間で切磋琢磨しながら働けるのは理想かもしれないし、普段は運用ばかりで技術的なことが仕事であまりできないときはある。
サービスを提供しているうえで運用を蔑ろにはできない。割り切ろう。

だがしかし、君の会社は素敵なことに定期的にLT大会や勉強会が開催されていたはず。
上長から指示された仕事以外で挑戦してみると自分の知らない知識を得られることができるかもしれない。
社内がだめなら、ちょっと外に目を向けるといろんな外部のイベントもたくさんある。

基本的にコミュ障で引きこもりの自分はLT大会に出たり、外部のイベント参加はハードルがすごく高くて無理だしんどいって思うかもしれないけど、なにも行動起こせなかったなって思うほうがしんどいです。

だいたいのことはなんとかなるけど、なんとかするのは自分しかいない。
どうしても行動を起こせないなら、同期を誘ってみるといいかもしれない。
ひとりじゃないだけで、一歩が出しやすくなるはず。
同期に恵まれたことに感謝を忘れずに。

あとは、技術=エンジニアとしての価値だと勘違いしていたと思うけど、
技術以外にも大切なことはたくさんあるはず。エンジニアとしての価値を高めるために必要ものがいくつかあって、そのうちの一つが技術だとおもうから、他のことにも目を向けよう。
こうやってQiitaに技術以外のこともアウトプットしてみるとか。

## 新卒の自分がマネジメントをやることになって怯えているキミへ
テックリードを目指しているわけではない人は特に。
プロジェクトリーダーを任せてもらう機会がいずれくるかもしれない。
もしその機会がきたら、完璧にプロジェクトを回さないと、というマインドを一回捨てましょう。
場数を踏んで慣れていくこともたくさんある。はじめからなんでもできる人間はいない。

チームメンバーに恵まれているので、すぐに一人でなんとかしなきゃと思うのをやめて、メンバーに支えてもらうのも一つの形だと思う。

マネジメントに正解はない。
チームメンバー重視の人もいれば、プロジェクト重視の人もいれば、サービス重視の人もいる。
正解がないものの完璧を目指すのは鬱になるから。

困ったら、上長でもメンバーにでも第三者でもいいから、どうしたらいいか相談すると良いでしょう。
何かを解決するためではなく、人に話す事によってやりたいこと、やらなきゃならないことが整理できるもの。
ラバーダックはおすすめ。
もしくは見本を見つけるとマネジメントのイメージがつくかもしれない。

## タスクがとっ散らかってしまうキミへ
マルチタスクが苦手というよりか、優先度、重要度、緊急度の総合点をぱぱっとつけるのが下手なキミ。
上から頼まれた仕事を淡々とこなす、受け身の姿勢がものすごく悪というわけではないけれど、自分から発信できるようになれば、自分が楽になれる道があるのかもしれない。
本当にやる必要があるのか。サービス影響がないなら期限を延ばしてもよいのではないか。
似たような案件をやっている人に自分のタスクを依頼したり、ついでに自分が巻き取れそうなことがあるなら進んで手をあげてやってみたり。視野を広げると、必然的に状況を整理する必要があるし、他の人に総合点をつけてもらうのもあり。

あとは具体的な案だと、よく聞くTODOリストを書くのはすごくいいと思う。
自分はTODOリストを作るよりもスケジュール（自分の場合はgoogleカレンダー）にこの時間をこれをやる。誰に連絡をするを予定に入れて整理するようになった。もし予定通りにいかない場合、スケジュールの中で期限が先のものや自分ひとりで完結するものを次の日のカレンダーに移動するようにしている。

見積もりは自分が思っているよりもバッファをもっても良いです。
サボっているわけではなく、任されるタスクが増えれば増えるほど、次のタスクの準備、整理をする時間が必要になってくる。
もちろん、急に問い合わせがきたり障害が起こって作業ができない可能性もある。
そのたびにすみませんってなるとメンタルにくるからその調整がとれるようになるといいね。
自分の精神衛生上バッファ作戦を取るのも一つあり。

## まとめ
ものすごく自己満足のメッセージになってしまったけど、自分が変わらないと一生この不安を抱えていくんだろうなという不安を常に抱えていた気がする。ちょっとだけ自分が頑張ることで解消されるものがあったから、同じ不安を抱えている人にちょっとだけ頑張ってほしい。
GCP Cloud Functions (Python) 備忘録

# 1. Deploy Functions

```
gcloud functions deploy .
```

# 2. Cloud Functionsでentrypointを指定する

```py:script_cloud_functions.py
def function_name():
    print("hello world")
```

- `--set-build-env-vars GOOGLE_FUNCTION_SOURCE=script_cloud_functions.py`
- `--entry-point=function_name` (`GOOGLE_FUNCTION_TARGET` これでもOKなはず)

```
gcloud functions deploy test-function \
    --gen2 \
    --runtime python312 \
    --set-secrets SLACK_WEBHOOK_URL=slack-webhook-url-dev:latest \
    --set-build-env-vars GOOGLE_FUNCTION_SOURCE=script_cloud_functions.py \
    --project $PROJECT \
    --region $REGION \
    --service-account test-function@${PROJECT}.iam.gserviceaccount.com \
    --source . \
    --entry-point=function_name \
    --allow-unauthenticated \
    --trigger-http
```

[Cloud Run and Cloud Functions environment variables](https://cloud.google.com/docs/buildpacks/service-specific-configs#and_environment_variables)

# 3. invoke cloud function

```
gcloud functions call $FUNCTION_NAME \
    --gen2 \
    --project $PROJECT \
    --region $REGION \
    --data "{\"specversion\": \"1.0\",\"source\": \"//cloudaudit.googleapis.com/projects/test-project/logs/data_access\",\"type\": \"google.cloud.audit.log.v1.written\", \"id\": \"projects/test-project/logs/cloudaudit.googleapis.com%2Fdata_access1234567123456789\", \"data\": {\"protoPayload\": {\"resourceName\": \"projects/_/buckets/sample-bucket/objects/filename.png\"}}}"
```
rubyタグとは？

先日、デザイン上ふりがなを振らなきゃいけない機会に遭遇し、初めてrubyタグ関連を知りました。
自分の備忘録も兼ねて記事残します。

## rubyタグとは
テキストにルビ（ふりがな）を振るためのマークアップ要素です。
命名なんかだじゃれみたいで笑った。
注釈で使ったりもあるらしいですが、あまり一般的ではないとのことです。

> HTMLの要素で、ベーステキストの上、下、隣に描画される小さな注釈であり、よく東アジアの文字の発音を表すのに使われます。他の種類の注釈にも使われることがありますが、この使い方はあまり一般的ではありません。
> mdn web docs（https://developer.mozilla.org/ja/docs/Web/HTML/Element/ruby）

## rubyタグの使い方
めちゃめちゃシンプルでした。

```html
<ruby>
    亜米利加<rt>あめりか<rt>    
<ruby>
```

全体を`<ruby>`で囲い、ふりがな部分を`<rt>`で囲うだけ。
上記のコードでこんな感じになりました。
![スクリーンショット 2024-03-14 8.54.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2940151/6ea25aa3-01f3-2dfb-8d1a-8bce98d5122d.png)

もちろんcssでスタイリングも可能。

``` css
ruby {
  font-size: 0.8em;
  color: #ff0000;
}

rt {
  font-size: 0.5em;
  color: #ff0000;
}
```

## 対応ブラウザ
2024年現在、普通に問題なく使えますね。

![スクリーンショット 2024-03-14 9.00.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2940151/2fc21eb5-ee49-fa7e-d996-86b5912e0fc7.png)
表作るのめんどくさかったので[mdn](https://developer.mozilla.org/ja/docs/Web/HTML/Element/ruby)さんから拝借。

## rbタグ・rpタグもあるらしい
なんか調べてたら出てきたので書きます。
もちろん、rubyタグと併用して使います。


- rbタグ：ふりがなを振る対象のテキスト
- rpタグ：rbタグが未対応のブラウザでふりがなが普通のテキストサイズで表示される際に、（）で囲って表示させる

### rbタグ
漢字それぞれにふりがなを振りたいときに使えるみたいです。
``` html
<ruby>
    <rb>亜</rb><rb>米</rb><rb>利</rb><rb>加</rb>
    <rt>あ</rt><rt>め</rt><rt>り</rt><rt>か</rt>
</ruby>
```

### rpタグ
``` html
未対応ブラウザで表示崩れしないために使うみたいです。
以下コードで、亜米利加（あめりか）と表示させます。
<ruby>
    <rb>亜</rb><rb>米</rb><rb>利</rb><rb>加</rb>
    <rp>（</rp><rt>あ</rt><rt>め</rt><rt>り</rt><rt>か</rt><rp>)</rp>
</ruby>
```

ただ、対応ブラウザを見る感じそこまで実装しなくてもいいのでは？という意見もありました。
状況に応じてって感じですかね。

## まとめ
htmlでもまだまだ知らないことたくさんあるなーって思います。
ふりがなかー擬似要素でやるかーでなにも調べず実装しなくてよかったです。
【Laravel】PHPStanをGitHub上でDockerの中で実行する

# はじめに

こんにちは、プログラミングを始めて約3年のエンジニアのkeitaMaxです。

前回、PHPStanをGitHubActionsでGitHubにPull Requestを出した時に、テストできるようにしました。

前回の記事

https://qiita.com/keitaMax/items/46102fd5a07e7c86168c


ymlファイルでGitHubのテスト環境のPHPバージョンなどの記載をしたら、PHPバージョンアップの対応をした時に修正し忘れそうだ思ったので、

今回は、それをGitHub上でDockerを立ち上げて、PHPStanがDocker上で動くように修正したいと思います。


# GitHubActionsのymlファイルの修正

```yml:phpstan.yml
name: LaraStan
on: [pull_request]

jobs:
  phpstan:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./src
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: "8.2"
          tools: composer, cs2pr
          coverage: none

      - name: Composer install
        run: composer install

      - name: Larastan install
        run: composer require nunomaduro/larastan --dev

      - name: Run PHPStan
        run: vendor/bin/phpstan analyze

```

もとは上のようだったファイルを、以下のように修正しました。

```yaml:phpunit.yml
name: phpunit

on: [pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./src
    steps:
      - uses: actions/checkout@v2
      - name: docker-compose up
        run: |
          # docker-compose build
          docker-compose up -d
      - name: composer install
        run: |
          docker compose exec app composer install
      - name: Laravel Settings
        run: |
          docker-compose exec -T app cp .env.example .env
      - name: phpunit
        run: |
          docker compose exec app php artisan test
```
PHPの設定を色々やっていたものをDockerを立ち上げるように修正しました。

# GitにPushしてGitHubで実行する

これをGitHubにPushすると以下のように実行され、全てにチェックがつきました。

![スクリーンショット 2024-03-12 23.13.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/5c5cb13c-fe50-631c-8383-9a802a80c0ed.png)

# 失敗させてみる

ちゃんと動いているかを確認するためにわざとLaraStanのテストを失敗させてみます。

```php
public function count():int
```
これを以下のようにして、PHPStanが失敗するようにします。

```php
public function count()
```
PHPStanのLevelがMAXなので、これでエラーになるはずです。

これでPushすると、以下のように失敗しているので、正しくテストが実行できていることが確認できました。

![スクリーンショット 2024-03-12 23.20.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/16786d8a-6125-fc1d-4c1f-df35199aeb39.png)



# おわりに

Dockerを使うと簡単にテストもできるし、DockerのPHPバージョンを変更すれば、開発環境とPHPバージョンとか諸々を合わせられるので便利だなと感じました。

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！
【Python】デフォルト引数値は、関数実行時に計算されるわけではないので注意

Pythonでは関数の引数にデフォルト値を設定することが可能です。ただし、リストや辞書のような変更可能なオブジェクト、または関数をデフォルト引数として使用する場合は、注意が必要です。

以下のコードでは、1秒おきにUNIX時間が表示されるはずですが、実際には同じ数字が3回表示されます。これは、`n=time.time()`という引数が、関数が定義された時に一度だけ評価されるためです。そのため、表示される3つの数字はすべて、関数が定義された瞬間の時刻となります。

```py
import time

def printer(n=time.time()):
    print(n)

for _ in range(3):
    printer()
    time.sleep(1)

# 出力：同じ数字3つが表示された
```

公式ドキュメントによれば、

> デフォルト引数値は関数定義が実行されるときに左から右へ評価されます。 これは、デフォルト引数の式は関数が定義されるときにただ一度だけ評価され、同じ "計算済みの" 値が呼び出しのたびに使用されることを意味します。（中略）このような動作を避けるには、デフォルト値として None を使い、この値を関数本体の中で明示的にテストします。

とされており、前述のコードを修正するのであれば、以下が適切なコードとなります。

```py
def printer(n=None):
    if n is None:
        n = time.time()
    print(n)
```

ちょっとしたプログラムであれば問題ありませんが、Webアプリなどを構築する場合、サーバーが起動した時刻で計算され続ける可能性があり、注意が必要ですね。（まんまと引っ掛かりました）

# 参考文献
[8. 複合文 (compound statement) - Python3.9.18ドキュメント](https://docs.python.org/ja/3.9/reference/compound_stmts.html#function-definitions)
製造業の品質管理とソフトウェアのQA(2)

## 1. はじめに
[製造業の品質管理とソフトウェアのQA](https://qiita.com/pbjpkas/items/d950c213bcefccd57bbb)の続きです。

製造業の品質管理をソフトウェア開発の参考にするなら設計工程も込みで参考にするとよいでしょう。

## 2. 製造業の設計工程の特徴
### 2.1 試作を繰り返す
こちらは[株式会社Shiftall](https://ja.shiftall.net/)の公式ブログ記事ですが、「[IoT設計製造のテンプレ・ガントチャート～Shiftall流、設計製造のポイントを添えて](https://ja.blog.shiftall.net/archives/2291/)」にてEVT1 → EVT2 → DVT → PVT → MP（量産）と数回の試作を経て量産に至ることが示されています。また、ソフトウェアはEVT1用ソフト、EVT2用ソフト、DVT用ソフト、工場検査モード実装、工場検査治具用ソフト、PVT/量産用ソフトと段階的に開発しています。

製造業の設計工程は試作を繰り返して完成度を上げていくのが特徴です。また、段階的にソフトウェアを開発してハードウェアチームや工場へリリースするのはアジャイルぽくもあります。

### 2.2 現実に合わせる
かつて筆者がプログラマだった当時、ハードウェアのエンジニアからこれとこのレジスタは値をいろいろ変えて検討したいから簡単に変えられるようにしてほしいとリクエストされて機能を追加したりしていました。

試作品を手にしたエンジニアが設計、評価する過程であれをもっとよく見てみたい、これはパラメータをいろいろ変えて試して良い方を採用したいというのはごく当たり前のことです。厳密なウォーターフォールであればそういったリクエストは要件定義の時点でなされるはずですがそれは無理な話というもの。むしろ三現主義、現場、現物、現実に合わせて課題解決を図ります。

## 3. アジャイル開発に取り入れられる製造業のプラクティス
製造業の設計工程は大きなくくりでいえばウォーターフォールですがその対立項として登場するアジャイル開発は製造業のプラクティスをいろいろと取り入れているようです[^1][^2][^3]。「[「アジャイル」を語る上で「トヨタ生産方式」が欠かせない理由（大越章司）](https://www.itmedia.co.jp/enterprise/articles/1704/28/news051.html)」では次の製造業のプラクティスが紹介されています。

- ポカヨケ、ムダの排除
- 自行程完結
- 見える化
- カイゼン、アンドン

## 4. おわりに
製造業の設計工程はウォーターフォールといっても教条的なものではなく、試作を繰り返して段階的に開発を行い、現実に合わせて柔軟に対応します。

製造業のプラクティスは必ずしもソフトウェア開発に応用できるとは限らないものの、例えばパブリックベータ版をリリースして市場の反応を認識し必要に応じて修正してから正式版をリリースするのは製造業の三現主義をソフトウェア開発へ応用したものと言えます。

製造業の品質管理をソフトウェア開発の参考にするなら製造工程だけでなく設計工程も含めて参考にするのがおススメです。

[^1]: [変化を味方につけるアジャイル開発（SEC journal 第44号 平鍋健児）](https://www.ipa.go.jp/archive/digital/secjournal/44.html)
[^2]: [トヨタウェイとアジャイル（竹腰重徳）](https://www.pmaj.or.jp/online/1212/message7.html)
[^3]: [ソフトウェア開発組織における生産技術に関する研究（居駒幹夫）](https://shizuoka.repo.nii.ac.jp/records/6025)
Raspberry Pi OS 2024-03-12 Release-note 翻訳

（追記：2024/03/22に、Raspberry Pi OS 2024-03-15 がリリースされています）
https://qiita.com/utaani/items/1b6830ee5e3f65d06b13

https://downloads.raspberrypi.com/raspios_armhf/release_notes.txt

2024-03-12:
  * 画面構成にヘッドレス解像度の設定を追加
  * Raspberry Pi Configuration から Wayland のヘッドレス解像度の設定を削除
  * Raspberry Pi 5 の電源ボタンの処理を改善
  * タスクバーのポップオーバー ウィンドウを従来のウィンドウに置換
  * シャットダウン アシスタントはログアウト時にすべてのユーザー プロセスを閉じるように
  * Wayvnc を更新し、さまざまな VNC クライアントとの互換性を向上
  * Wayvnc は systemd によって制御されるように
  * オーディオデバイスが接続されていない場合、タスクバーのオーディオアイコンは非表示に
  * ドラッグ アンド ドロップ操作中にはマウス カーソルが置き換わるように
  * raspi-config で EEPROM をアップグレードできるように
  * Bluetooth およびネットワーク メニューを開くときの速度が向上
  * ダークテーマでの一部のウィジェットの表示を調整
  * 代替ウィンドウマネージャーとの互換性を向上
  * バグ修正 - 複数のファイル マネージャー確認ダイアログがオーバーレイされるのを防止
  * バグ修正 - ファイルマネージャーでドラッグアンドドロップすると、間違ったファイルが移動していた
  * バグ修正 - ボリュームおよび Bluetooth メニューでのメモリリーク
  * バグ修正 - プラグインとタスク マネージャーで GPU 負荷が正しく報告されない場合があった
  * バグ修正 - GTK 以外のヘッダーバーを使用してウィンドウを閉じるとクラッシュする
  * バグ修正 - タッチスクリーン上の偽のボタン ホバー ハイライト
  * バグ修正 - 他のモニター上のウィンドウがタスクバーから非表示になる
  * バグ修正 - 電力監視の電圧低下検出を修正
  * バグ修正 - wayfire キーボード レイアウト設定が読み込まれない場合がある
  * fbturbo xorg ビデオ ドライバーは役に立たなくなったため削除
  * Chromium は 122.0.6261.89 に更新されました
  * Firefoxは123.0にアップデートされました
  * Raspberry Pi ファームウェア 6e0ae774407d68659b50cfbeb9f493ed16718866
  * Linux カーネル 6.6.20 - 6f16847710cc0502450788b9f12f0a14d3429668