OmniAICreator/Qiita-1.07M huggingface dataset:
windows10環境でStable Diffusionの環境を構築してみた

話題のAI画像生成ですが、興味があったのでセットアップからやってみました。

# グラボの確認

「表示メモリ」4000MB以上だと良い、ということで確認。

ファイル名を指定して実行(Windowsキー + R)

dxdiag

と入力しEnter

![bbbキャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/80c35db7-adc2-4389-5191-274ba67556f7.png)

ディスプレイ1, 2のどちらかに書いてあります。

私のは6052MBなので、OK！ということでやってみました。

# Pythonのインストール

バージョン `3.10.6`

以下からインストールできます。

https://www.python.org/downloads/release/python-3106/


# gitのインストール

バージョンは最新版をインストールしてください。
以下からインストールできます。

https://git-scm.com/download/win

表示されるものを、デフォルトの状態で次へ進んで行ってインストールまでいければOKです。


# Stable Diffusionのインストール

今回は、容量が大きく余裕があったDドライブにインストールすることにしました。
モデルが増えてくると、どんどん肥大化していく可能性があるからです。
適当な名前でフォルダを作成します。今回は「stable-diffusion-202308」としました。
ターミナルでその作成したフォルダ直下まで行き、以下のコマンドでcloneしてください。

```
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
```

# xformersのインストール

これを入れると、
- `webui-user.bat`をクリックするだけで、自動起動される。
- 画像生成時間が早くなる
のメリットがあるので今回入れてみます。

**※「xformers」は、NVIDIA社のグラボ以外は使用できません**

ファイル名を指定して実行(Windowsキー + R)

```
cmd
```

と入力しEnter。
以下のコマンドでインストールしてください。

```
pip install xformers
```

# `webui-user.bat`の編集

git cloneしたリポジトリ内に、webui-user.batがあるので、テキストエディタなどで開いてください。

```
set COMMANDLINE_ARGS=
```

という行があるので、そこに追記します。
以下の基準を参考にし、設定してください。

- ハイスペックGPU(VRAM12GB以上) : --autolaunch --xformers 
- ミドルスペックGPU(GTX10xxなどはこちら) : --autolaunch --medvram --xformers
- GTX16xxシリーズ: --autolaunch --precision full --no-half --medvram --xformers
- VRAM4GB以下のロースペックGPU : --autolaunch --lowvram --xformers

設定後、webui-user.batをダブルクリックしてバッチを起動してください。

初回起動時は、遅くて30分くらいかかることもあります。じっくり待ちましょう。

完了すると、自動的に

[http://127.0.0.1:7860/](http://127.0.0.1:7860/)

が開きます。

# 画面の確認

以下のような画面になります。

![FireShot Capture 002 - Stable Diffusion - 127.0.0.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/5f25baf1-26da-5600-c5d4-0773352be3af.png)


これで完了です。
VanJSのチュートリアルを触ってみた

こちらの記事でVanJSの紹介があり、軽量で依存関係の無いReactive UI フレームワークとのことだったので、公式ドキュメントのチュートリアルを元に触ってみます。

https://zenn.dev/ryo_kawamata/articles/1ad6e51eed13ae

最新のバージョン（2023/08/17時点）の1.0.2では `.min.js`は**1.6kb**と超軽量です。

# VanJSとは？

> VanJS is an ultra-lightweight, zero-dependency, and unopinionated Reactive UI framework based on pure vanilla JavaScript and DOM. Programming with VanJS feels like building React apps in a scripting language, without JSX.

VanJS は、純粋なバニラ JavaScript と DOM に基づいた、超軽量、依存関係なし、固定観念のない Reactive UI フレームワークです。 VanJS を使用したプログラミングは、JSX を使用せずにスクリプト言語で React アプリを構築するような感じです。

https://vanjs.org/

# 触ってみる

## 環境準備

```tree
├── index.html
└── main.js
```

今回は公式ドキュメントからCDNで、VanJSをインストールします。

```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

</body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/vanjs-org/van/public/van-1.0.2.nomodule.min.js"></script>
<script src="main.js"></script>
</html>
```

## チュートリアルを触ってみる

元のチュートリアルから、コードの整形とコメントを追加してます。

### Hello Worldを表示

https://vanjs.org/tutorial#your-first-vanjs-app-a-simple-hello-page

```javascript:main.js
// HTMLエレメントを取得
const { div, p, ul, li, a } = van.tags

const Hello = () => div(
  // ()内に文字を入れることで、テキストを表示
  p('👋Hello'),
  // ulの引数にliを入れることで、ul>liのDOMを作成
  ul(
    li('🗺️World'),
    li(
      // 第一引数にオブジェクトを入れることで、属性を追加
      // 第一引数にオブジェクトを入れた場合は、テキストは第二引数に入れる
      a({ href: 'https://vanjs.org/' }, '🍦VanJS')
    ),
  ),
)

van.add(document.body, Hello())
```

### DOM要素の削除

https://vanjs.org/tutorial#removing-a-dom-node

```javascript:main.js
// HTMLエレメントを取得
const { a, button, div, input, li, ul } = van.tags

// listDomに追加する要素
const ListItem = ({ text }) => {
  // stateオブジェクトを作成
  const deleted = van.state(false)

  return () =>
    // stateの値によって表示を変える
    deleted.val
      // trueならnullを表示
      ? null
      // falseならliを表示
      : li(
          text,
          // onclick: () => {}でクリックイベントの属性を追加
          // クリックしたらstateの値をtrueに変える
          a({ onclick: () => (deleted.val = true) }, '❌')
        )
}

const EditableList = () => {
  // 変数にすることで、DOM表示に使えたり、value取得に使えたりできる
  const listDom = ul()
  const textDom = input({ type: 'text' })

  return div(
    textDom,
    ' ',
    button(
      {
        // van.add(親要素, 子要素)で子を親の末尾に追加
        // textDom.valueでinputで入力した値を取得できる
        onclick: () => van.add(listDom, ListItem({ text: textDom.value })),
      },
      '➕',
    ),
    listDom,
  )
}

van.add(document.body, EditableList())
```

# まとめ

サイズがたった1.6kbなので、Reactを入れるほどでもないけど、Vanilla JSで動的UIを作るのは辛いという場合に良いな思いました。


# 最後に
### GoQSystemでは一緒に働いてくれる仲間を募集中です！

ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=364d63c861c796b6ac4b
windows10でDドライブにcdコマンドで移動できない時は

コマンドラインでDドライブに移動しないと、という状況があったのですがまさかの躓きました。

`cd D:/`

で行けると思っていたのですが

![111キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/12b4f7fa-9c4e-68d5-1d66-75264a356a29.png)

あれ…？ Cのまま？

調べてみると、

`cd/d D:/`

としないとダメの様でした。

知らんかった…

![222キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/20b8f38d-1d73-aea1-9cb2-6825154b696c.png)

行けました。
CameraXでAndroidのカメラを起動してみる

備忘録として、cameraXを用いてandroid端末のカメラを起動してみる。

最終的に画像認識エンジンを走らせてみたい！

以下を参考にしてみる。
[cameraXスタートガイド](https://developer.android.com/codelabs/camerax-getting-started?hl=ja#0 "cameraXスタートガイド")

詰まった箇所


**「CameraXApp.app モジュールの build.gradle ファイルを開き、CameraX の依存関係を追加します。 」**

以下のコードをbundle.gradle.ktsに追加するのだが、エラーが出る。
```
dependencies {
  def camerax_version = "1.1.0-beta01"
  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  implementation "androidx.camera:camera-video:${camerax_version}"
  implementation "androidx.camera:camera-view:${camerax_version}"
  implementation "androidx.camera:camera-extensions:${camerax_version}"
}
```
上記を以下のように書き直したら動くようになった。

```
var camerax_version = "1.1.0-beta01"
    implementation ("androidx.camera:camera-core:${camerax_version}")
    implementation ("androidx.camera:camera-camera2:${camerax_version}")
    implementation ("androidx.camera:camera-lifecycle:${camerax_version}")
    implementation ("androidx.camera:camera-video:${camerax_version}")
    implementation ("androidx.camera:camera-view:${camerax_version}")
    implementation ("androidx.camera:camera-extensions:${camerax_version}")
```


#### 追記 2023/9/7
元々Groovyでgradleファイルが書かれていることが多いので、それをkotlinとして書くためには()や""の追加が必要だとわかった。
[ビルド構成を Groovy から KTS に移行する](https://developer.android.com/studio/build/migrate-to-kts?hl=ja)




**「res/layout/activity_main.xml の activity_main レイアウト ファイルを開き、次のコードに置き換えます。」**

Android Studioで新規プロジェクトを作成するときに「Empty Activity」を選ぶとactivity_main.xmlが無い。どうやらJetpack Composeを使うことになるとのこと。


![スクリーンショット 2023-08-17 21.23.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67885/e0365bae-886e-e9a5-349f-b242a3270072.png)




なので「Empty Views Activity」を選択すれば、今まで同じようにactivity_main.xmlがある。

以上でAndroid端末のカメラを起動することができた。
New Relicのモバイルアプリ使ったことありますか？

# 概要
New RelicにはiOSとAndroidで動作するモバイルアプリがあるのをご存知でしょうか？
移動中や出先でアラートの詳細やシステムの状態を確認する際に、わざわざPCを開かなくてもNew Relicの画面をモバイルアプリで気軽に確認することができます。

それでは、モバイルアプリの基本的な利用方法を試していきます！

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/dac61c29-77b4-10f1-15cb-f40148afd476.png">

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート")
:::

# 手順
## 1. New Relicのモバイルアプリをダウンロード
こちらのリンクからiOSかAndroidのモバイルアプリをダウンロードします。

https://docs.newrelic.com/docs/mobile-apps/mobile-apps-intro/

New Relicの環境を持っていない方は、こちらからサインアップしてください。

https://newrelic.com/jp/sign-up-japan

## ２. モバイルアプリを起動してログイン
ダウンロードが完了したら、モバイルアプリを起動し、New Relicにログインします。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/fa8a7fd2-805b-3b46-5a66-3b748635e4bf.png">

## ３. 各種画面を表示
ログインするとまずはHome画面が表示されます。
主な機能が画面下部に並んでいるので、タップすることで各画面に切り替えることができます。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/97111981-85f5-079c-48c4-fe8b003b77f8.png">

### Home
Home画面ではお気に入りとして登録しているエンティティが一覧で表示されます。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/fc1d737b-69ff-3998-a91b-007423b74e50.png">

エンティティを選ぶとこのようにレスポンス等を確認することが可能です。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/7c6d51e5-2536-e89d-3f32-75c487475a0e.png">

### Explorer
Explorer画面は、ブラウザでNew Relicを表示したときのAll Enetitiesのような画面となっており、カテゴリーからエンティティにアクセスできます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/ac5016d0-a345-c6d4-0077-20291a415f67.png">

### Dashboard
Dashboard画面では、ダッシュボードが一覧で表示されます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/c8152c90-6ea1-abc8-ec8b-b1db083d6282.png">

選択するとモバイルの画面サイズに合わせてダッシュボードが表示されます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/6bb98343-678c-3341-0419-fea7a9dc0dd6.png">


### Alert
Alert画面では今発生しているIssueとIncidentを確認することができます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/3df5649a-a4a7-d55b-2f2d-e660841298df.png">

Issueを選択することで、詳細を確認することができます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/db7cb830-79f7-1913-b7b9-cb671c1febb4.png">

### Query
Query画面では、NRQLを使用してデータを検索することが可能です。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/e8afefcf-ff31-1083-2a62-56488c5c56f4.png">

ブラウザでNew Relicを使っているときと同じように、文字の入力時に予測を出してくれるので、スマホの画面でも気軽にNRQLを使ってデータをクエリできます。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/9f2a9a42-9e8d-6181-3585-4035d966aea9.png">


# まとめ
New Relicのモバイルアプリの基本的な使い方を紹介しました。
よくできているアプリなのでぜひ一度お試しください。

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート")
:::
LXDで32bitコンテナイメージが使えなくなって悲しい気持ちになった件

2023/7/4 Linux Containers プロジェクトで開発が進められていた LXDがCanonicalに移ることになったらしい・・

- LXDはCanonicalの傘下に入りました
  https://linuxcontainers.org/ja/lxd/

この記事のなかで・・

> Linux Containers のイメージビルドは、Canonical が提供するシステムに依存しなくなり、イメージビルドは x86_64 と aarch64 に限定されます。

という変化がしれっと書かれていました。

私は仕事でもプライベートでもLXDを活用していますが、プライベートでは RaspberryPi OS 32bit の RaspberryPi 3 を使っているので、新しいコンテナインスタンスを作成することができなくなることや、64bit版に移行しなければならないのかと思うと、とても悲しい気持ちになりました・・・

一方で、LXD をフォークした Incus という新たなプロジェクトも立ち上がったようなで、こちらの動向も見守っていこうかと思います。

- Incus の紹介
  https://linuxcontainers.org/ja/incus/introduction/
簡単なチャットボットを作ってみよう（準備編）

船井総研デジタルのtakizawaです。
今回は簡単なチャットボットアプリケーションを作ってみようと思い記事にしました。
お付き合いいただければと思います。

# チャットボットとは？

「チャットボット（英: chatbot）は、もともとはチャッターボット（英: chatterbot）とよばれ、テキストや音声による対話を通じて人間的な会話の模倣を目的としたソフトウェアアプリケーションで、通常はオンラインで使用される。」
(Wikipediaより抜粋)

ということで、ここではテキストベースでボットと会話するアプリケーションを作成していこうと思います。

# 構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473569/b474c92d-3dcc-9709-3f39-63ecf60356ce.png)

現状はこのような構成を考えています。まずはローカルでフロントエンドとバックエンドを連携させバックエンドからAzure Open AIにアクセスすることを目標とします。
構築する順序は次の順番で考えています。
1. バックエンド
1. フロントエンド
1. Azure Open AIと連携

※今回筆者はVSCode＋WSL＋devcontainerの組み合わせを用いて開発を進めていきます。（Dockerデスクトップは使用しません！またdevcontainerの試用は必須ではないです。）
WSL2を使用できるようにする準備とdevcontainerを使用する方法は[こちらの記事](https://blog.jp.square-enix.com/iteng-blog/posts/00024-wsl2-docker-ce/)が参考になると思いますのでここでの説明は省かせていただきます。

# バックエンドの開発環境構築

[チュートリアル: ASP.NET Core で Web API を作成する](https://learn.microsoft.com/ja-jp/aspnet/core/tutorials/first-web-api?view=aspnetcore-7.0&tabs=visual-studio-code) の記事を参考に環境構築を行います。

## プロジェクトの作成
バックエンドの開発コンテナに接続してある状態でVisual Studio Codeのターミナルを開き、```dotnet new webapi -o <プロジェクト名>``` でプロジェクトを作成します。

## https開発証明書のインポート

筆者環境ではWSLで動いているUbuntu上のコンテナで稼働するのでhttps開発証明書をUbuntu（devcontainer）にインポートする必要があります。

1. Windows上で証明書を出力する。
    windowsでPowerShellを開き証明書を出力するフォルダに移動したのち```dotnet dev-certs https -ep https.pfx -p $CREDENTIAL_PLACEHOLDER$ --trust```コマンドを実行します。すると```https.pfx```というファイルが作成されていると思います。

1. ```https.pfx```ファイルをバックエンドのフォルダの直下に移動します。
1. バックエンドの開発コンテナに接続してある状態のVisual Studio Codeのターミナル上で```https.pfx```ファイルを配置したフォルダで```dotnet dev-certs https --clean --import ./https.pfx --password $CREDENTIAL_PLACEHOLDER$```コマンドを実行します。

DevContainerを使わずにWindows上で構築している場合は[こちらのページ](https://learn.microsoft.com/ja-jp/aspnet/core/tutorials/first-web-api?view=aspnetcore-7.0&tabs=visual-studio-code)を参考に証明書を準備してください。

ここまで出来たら一度、稼働確認をしてみましょう。

# フロントエンドの開発環境構築

フロントエンドの開発コンテナに接続してある状態でVisual Studio Codeのターミナルを開き、```npm init vue@latest``` でプロジェクトを作成します。

| 設定内容 | 設定 |
|:--------|:-----|
| Project name | <プロジェクト名> |
| Add TypeScrpt? | Yes |
| Add JSX Support? | No |
| Add Vue Router for ... | Yes |
| Add Pinia for ... | Yes |
| Add Vitest for ... | 任意 |
| Add Cypress for ... | No |
| Add ESLint fro ... | Yes |
| Add Prettier for ... | Yes |

作成されたプロジェクトを実行して稼働確認をしてみましょう。

ここまででバックエンドとフロントエンドを実装していく準備ができました。

次回はバックエンドを実装していきたいと思います。

続編を投稿しました！！
[簡単なチャットボットを作ってみよう（バックエンド編）](https://qiita.com/fsd-takizawa/items/b0aba71ee46549a05ad2)
get_var_dump.php

```php
function get_var_dump($var) {
    ob_start();
    var_dump($var);
    return ob_get_clean();
};
error_log(get_var_dump(["apple", "key1" => true]), 3, __DIR__ . DIRECTORY_SEPARATOR . 'error.log');
```

```php
function save_var_dump($var) {
    ob_start();
    var_dump($var);
    error_log(ob_get_clean() . PHP_EOL, 3, __DIR__ . DIRECTORY_SEPARATOR . 'error.log');
}
```
RUNTEQに入って100日で1000時間学習してみた【学習記録のまとめ】

## はじめに
はじめまして！
RUNTEQに入学してから【100日で1000時間学習する】という目標を達成したので、改めて学習した内容をまとめていきたいと思います。

## 学習分野

1000時間の中で以下のような分野を学習しました。
- Ruby
- Ruby on Rails
- JavaScript
- GitHub
- SQL
- DB設計
- Linux
- Docker

## 内訳
学習分野のそれぞれの内訳は以下のようになります。Ruby、Ruby on Railsで700時間ほど学習に充てました。理由については後述します。
![スクリーンショット 2023-08-19 17.25.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517817/3ec259f4-133a-3aac-e7b9-2b317738b462.png)




## 主な学習教材
- スクールのカリキュラム
- ゼロからわかる Ruby 超入門
- プロを目指す人のためのRuby入門
- 独習Ruby
- Railsチュートリアル(〜CHAPTER8まで現在学習中)
- パーフェクト Ruby on Rails
- Ruby on Rails 6 実践ガイド
- Ruby on Rails 6 実践ガイド 機能拡張編
- Ruby on Rails 7ポケットリファレンス
- Everyday Rails - RSpecによるRailsテスト入門
- マンガでわかるデータベース
- スッキリわかるSQL
- プロになるためのWeb技術入門
- イラスト図解式 この一冊で全部わかるWeb技術の基本

## 1000時間を学習するにあたって意識したこと
### 1. モチベーション設計
この目標を達成するにあたり、モチベーション設計が大切だと考えたので学ぶ分野をまず初めに絞りました。1000時間という時間を考えた時に、何か複数の分野(React、Docker、Terraformなど)を並行して学ぶには足りない時間だと考えたからです。
その為、スクールではRuby on Railsが中心のカリキュラム構成だったため、Ruby、Ruby on Railsを重点的に学ぶことで、モチベーション低下を防ぎました。

### 2.イベント駆動型学習
スクール内ではイベントを自主的に企画できるようになっていたため、勉強会を企画しました。自分の思考の整理だったり、苦手だと感じている分野について企画し、これまで3度開催しました。企画した以上、わかりやすく教える必要があるという責任も生まれ、約150人以上の方に参加していただきました。今後も続けていきたいと考えています。
- **Gitをカレーに例えてチーム開発の流れを考えてみよう！**(https://hackmd.io/@0ybq7E7CT5GYxDP8A9clgA/rk9QeGWdh)
- **テストは何かを理解してRSpecの基礎に慣れてみよう！**（https://hackmd.io/@0ybq7E7CT5GYxDP8A9clgA/HJ2ylBHd3 ）
- **デバッグの方法をたくさん知ってエラーと仲良くなろう！**(https://hackmd.io/@0ybq7E7CT5GYxDP8A9clgA/S1PqjDmch)

### 3.GitHubに草を生やす
やはり数字として積み上がっていくのは気持ちが良いです。3ヶ月弱で800コントリビューション付けることができました。モチベーション設計の観点から学習初期は『草を生やすこと自体が目的』にはなっており、commitの粒度であったり、お作法的な部分で反しておりますが、やる気を維持する上では個人的には有効な戦略ではあったと考えています。
![スクリーンショット 2023-08-19 16.23.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517817/6dbe9d24-c908-2037-23ea-bd3638cc6dd9.png)

## 1000時間学習を通して成長したこと
1000時間学習した段階で実装力に関しては特に成長を実感しています。ここでいう実装力というのは僕の中で以下の２つに分けられると思っています。

### 公式ドキュメントを読んで実装手順を考える能力
カリキュラムが公式ドキュメントをもとに実装する要件が多かったため、Githubをはじめ、Railsガイドなどの公式ドキュメントを読むことには比較的慣れました。学習初期から一次情報から情報を参照するように癖づけられたことは非常に良かったと感じています。

### コードリーディング力
カリキュラム内で実務に近いWebサービスのバグ修正だったり、機能追加を行う実装に取り組みました。詳細は言えませんが、デバッガを用いて調査を行い、バグ原因箇所の特定、改修手順の把握、修正とコードを読みながら論理的に実装する能力が身につきました。

### 質問力
実装力とは別ですが、質問の作り方も初期から意識してきました。現場では担当タスクに工数が決められていることもあり、Webアプリ(https://hamattimer.app) を活用し、【限られた時間の中で、最小のテキストコミュニケーションで意図した回答がもらえるような質問】を意識しながら、実装を進めてきました。


## 今後の課題
### アルゴリズム
実装する上で冗長な書き方になってしまう事が多いため、paiza、AtCoderを活用し伸ばしていきたいです。

### 設計
個人開発をする機会も増えてきましたが、実装途中で設計で考え直す部分も出てきてしまっているので、引き続き開発を通して身につけていきたいです。

## その他
個人開発に関しても最近は楽しめるようになり、Next.jsとTypeScriptを使ってアプリも作ってみました。RUNTEQ内で青春に関するイベントが開催された際に、青春をテーマに作ったミニアプリです。
- おやつは何円まで?(https://oyatsu-ha-nanenmade.vercel.app/)
[![Image from Gyazo](https://i.gyazo.com/58a921905b17111c1e226d81081a6225.jpg)](https://gyazo.com/58a921905b17111c1e226d81081a6225)

## RUNTEQについて
カリキュラムの難易度、開催イベントの量、キャリアトレーナーなどをはじめとする運営陣の手厚いサポート、控えめに言っても受講してよかったと実感しています。最近カリキュラムがアップデートされたことや、何に挑戦するにしても受講生同士で協力したり、悩みも相談しやすい環境でもあるので、カリキュラムは難しいですが、本気でエンジニアになりたい方にとってはこれ以上ない環境だと思います。

## まとめ
これまでRuby、Railsを中心に学んできました。今後は、少しずつJavaScript、Linux、Dockerなどの学習も増やしていき、エンジニアとして成長できるように活動していきたいです！
最後まで読んでいただき、ありがとうございました！
ヘッドレスCMS、Kurocoについて



## はじめに
初投稿になります。
未経験からの転職のため、　調べたことの貯蓄として書き記していこうと思います。
今回は、ヘッドレスCMS、Kurocoを勉強してみたことについてです。

---

### CMSとは
　CMSとはWebサイトの作成を行う際にHTMLやCSSといった専門的な技術を保有せずとも、Webサイトの作成、管理、更新などを誰でも簡単に実現できるツール。 

### ヘッドレスCMSとは
　従来のCMSは、コンテンツを管理するバックエンドのシステムとコンテンツを表示するフロントエンドが組み合わせられてできているのに対し、ヘッドレスCMSはフロントエンド部分を「ヘッド」と表現し、コンテンツを表示するフロントエンド部分がないCMS。つまり、ヘッドレスCMSはコンテンツを管理するためだけのシステムのこと。
　ヘッドレスCMSにはWebページの表示を確認するためのフロントエンド部分がないのでCMS外で別に構築し、ヘッドレスCMSが提供しているAPI（Application Programming Interface）を用いてCMS外で構築したフロントエンドでコンテンツ情報を取得し、設定した場所に表示させることになる。


---

### 

**（従来のCMS）**   
WordPressなどの従来CMSは、コンテンツデータ（テキスト、画像、動画など）を表示させるフロントエンドと、これらのコンテンツデータを管理するバックエンドシステムが統合されて成り立っている。バックエンド側では、コンテンツデータの管理だけでなく、Wordpressテンプレートの管理も行っている。そのためフロントエンド側では、テンプレートを作成したり改修したりする際に、バックエンドが使用している言語に合わせる必要がある。
  
**（ヘッドレスCMS）**   
- ヘッドレスCMSには、フロントエンドがないため、バックエンドに集中してシステムの開発や改修を行うことができる。
- フロントエンドに当たる部分はCMS外で別に構築し、ヘッドレスCMSが提供するAPIでコンテンツデータを外部フロントエンドへ出力し、管理・運用。


**ヘッドレスCMSのメリット**
- フロントエンドの自由度が高い  
ヘッドレスCMSではフロントエンド部分が独立しているという特徴がある。
フロントエンドとバックエンドが完全に独立しているので、それぞれが言語などの配慮する必要がなく、開発や改修を行うことができる。

- APIを用いて外部のコンテンツデータを出力するため様々なサービスと連携できる。

- 表示速度が速い
フロントエンドとバックエンドの部分が完全に独立しているため、データベースへアクセスしてファイルを生成し、出力する必要はないため表示速度が速いというメリットがあります。 

- サイトの一部だけでも利用できる  
従来のCMSの場合、お知らせや製品ページなど、頻繁に更新したいページだけにCMSを導入することは難しいとされていた。ヘッドレスCMSは、必要な箇所にAPIを通じて該当する箇所を呼び出し、既存ページに反映させることが可能。

---


### Kurocoについて

KurocoとはAPIファーストのHeadless CMSです。
従来のCMSのようにシステムに縛られることなく、柔軟なシステムの構築が可能となります。
欲しい機能を、欲しい時に、欲しいだけ、選び取ってください。  
[Kuroco](https://kuroco.app/ja/docs/about/about-kuroco/) より

- **料金**  
  - 完全な従量課金  
  - 初期費用なし。1,100円/月の無料料金枠ですぐに始められる。
  - 概算月額料金を算出したり、定額契約もできる。  
[詳細](https://kuroco.app/ja/pricing/)

- **特徴**

    - 複数の会社が同時に開発できる
      - API連携で高速開発。タイムラグがない。
      - APIを管理画面から設計して、柔軟でスムーズな開発。
    - 技術スタックに囚われない
      - いつもの環境でコンテンツ追加。好きな言語で開発できる！
      - CMS構築のために新しく技術を習得しなくてOK！


### Kuroco でできること
- コンテンツ管理  
  - [コンテンツ定義]と[コンテンツ]メニューでコンテンツ管理ができる。  
「コンテンツ定義」とはコンテンツのグループのことで、「ブログ」や「お知らせ」といったグループで分けることができる。  
  - [コンテンツ]は、[コンテンツ定義]で分けたグループの記事を追加。  
  - [コンテンツ]→[タグ]でカテゴリーを設定できる。

- API連携  
フロントエンドと連携するためのAPIが用意されている。
新たにエンドポイントを作成することも可能。

- ファイル管理  
Webサイト内で利用する画像やテキスト・動画などのファイルをアップロード、管理できる。

- Kuroco Front（サーバホスティング機能）  
GitHubと連携(現在はGitHubのみ可能)。  
KurocoFrontは、CDNを利用した静的コンテンツホスティングサービス。独自ドメイン、TLS証明書やBasic認証、IPアドレス制限までを無料で利用することが出来る。

- 独自ドメイン設定  

- フォーム作成  
お問合せ内容も管理画面より確認できる。

- ログ管理
  - 「ログインログ」・「APIログ」など、様々なログの確認ができる。
  - [オペレーション]→[ログ管理]

- EC
  - 課金システムとの連携
  - 商品・SKU登録
  - 注文・売上げ管理
  - 定期課金システムの設定

- 多言語機能  
  複数言語のコンテンツを設定できる機能や閲覧者のアクセス元の国や都道府県の取得機能など

- CRM(Customer Relationship Management)機能   
  - 顧客情報管理
  - 会員の情報を細かく定義
  - メルマガ発行
  - セグメントメール配信

[参考](https://kuroco.app/ja/features/)  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492723/e0bb87ab-c6bf-070a-42fa-a05af0368587.png)

## 最後に

Kurocoには多くのことができるようですが、記事で紹介はとても少ないのが現状です。
Kuroco公式サイトでリファレンス、それを参考に一部機能を使ってWebアプリを作ってみたのでまたの機会にまとめたいと思います。
UFWを活用して特定の通信のみ許可する

今回はUFWの設定により、特定の通信のみ許可する方法について書いていきます。
実際に設定したサーバは`Ubuntu22.04`です。

## UFWとは
Ubuntuで使用されるファイアウォールの設定ツールです。
ちなみに`Uncomplicated Firewall`(複雑でないファイアウォール)の略です。
私は`Ubuntu FireWall`の頭文字を取ったものだと勘違いしていました；
その名の通り、`iptables`ファイアウォールの設定を楽に行えるようです。

## UFWの初期値は「すべての通信を遮断する」
UFWはデフォルトではオフになっていますが、これをオンにするとどう働くのでしょうか。
正解は「すべての通信が遮断される」ようになります。
UFWは、すべての通信を遮断しておいて、許可する通信のみ設定していく方式なのです。

ですので、サーバにSSH接続して作業する場合は、ターミナルを閉じてしまうと接続できなくなりますので注意が必要です。

## UFWを使ってみる
では、実際にUFWを有効化してみましょう。
```bash:ターミナル
sudo ufw enable
```

次にデフォルトの設定を確認してみます。
```bash:ターミナル
sudo ufw status verbose
```

`Default: deny (incoming), allow (outgoing)`と表示されるはずです。
これは「サーバへの入力はすべて`deny`(遮断)」、「サーバからの出力はすべて`allow`(許可)」を示しています。
UFWは外から内に入ってくる通信にのみ制御が可能です。
この状態で、別のターミナルからSSHログインを試してみると繋がらないはずです。

## UFWでSSH接続を許可してみる
初期状態ではサーバアクセスができないため、SSH接続を許可してみます。
```bash:ターミナル
sudo ufw allow 22/tcp
```

ちなみに遮断するには`sudo ufw deny 22/tcp`
定義自体を削除するには`sudo ufw delete deny 22/tcp`とする。

また、ポート番号の他にも「サービス名」で許可／遮断を定義することもできる。
`sudo ufw allow ssh`
ちなみに、サービス名とポート番号の組合せは以下から確認することができる。
`less /etc/services`

## もっと詳細に定義したい場合
UFWを使うと、もっと複雑な条件でも簡単に設定することができます。
正に痒い所に手が届くツールです。

### 特定のIPアドレスから、特定のポート番号に対してTCPプロトコルでの接続を許可
```bash:ターミナル
sudo ufw allow from 192.168.0.3 to any port 22 proto tcp
```
遮断するときは`sudo ufw deny from 192.168.0.3 to any port 22 proto tcp`

### 特定のサブネットから、特定のポート番号に対してTCPプロトコルでの接続を許可
```bash:ターミナル
sudo ufw allow from 192.168.0.0/24 to any port 22 proto tcp
```
遮断するときは`sudo ufw deny from 192.168.0.0/24 to any port 22 proto tcp`

### 特定のインタフェースから、特定のポート番号に対してTCPプロトコルでの接続を許可
```bash:ターミナル
sudo ufw allow in on eth0 to any port 22 proto tcp
```
遮断するときは`sudo ufw deny in on eth0 to any port 22 proto tcp`
## まとめ
このようにして、UFWを上手く使いこなし、ファイアウォールによるセキュアなサーバを作っていきたいと思います。
今回は以上です。
React Router v6で共通レイアウト的なことを実装

React Router V6で共通レイアウトのようなことをやりたかったので、
調べて実装できたので、やり方のメモを残す。

## 結論:"Outlet"を使う
Outletを使うことで実装できます。

例えば、ヘッダー、メインコンテンツ、フッターという構成でメインコンテンツを切り替えたいとします。
ヘッダーとフッターを共通レイアウトとして、下記のような共通レイアウトコンポーネントを作成します。
```typescript:Layout.tsx
import { FC } from "react"

//Outletをインポート
import { Outlet } from 'react-router-dom';


export const Layout: FC = () => {


    return (
        <>
            <header>
                ヘッダー
            </header>

            //ここが切り替わる
            <Outlet />

            <footer>
                フッター
            </footer>
        </>
    )

}
```
ポイントは、Outletの部分が切り替わるということです。
ルーティングは下記のように書きます。
```typescript:index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';


// コンポーネントのインポート
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { About } from './components/About';
import { Contact } from './components/Contact';

const container = document.getElementById('app');
const root = createRoot(container!); 

root.render(
    <React.StrictMode>

    <BrowserRouter>
        
        <Routes>
            
            <Route path="/" element={<Layout />}>
                <Route path="/home" element={<Home />} />
                <Route path="/about" element={<About />} />
                <Route path="/contact" element={<Contact />} />
            </Route>
        </Routes>
        </BrowserRouter>
    </React.StrictMode>

);
```
LayoutのRouteで切り替えたいコンポーネントのRoute(メインコンテンツ)をネストします。
LayoutコンポーネントのOutletの部分がネストしたコンポーネントに置き換わる仕組みです。

## 余談:共通レイアウトを適応したくない場合
中には、共通レイアウトを適応させたくないページもあるでしょう。
それは簡単に実現できます。
例えば、Loginというコンポーネントがあるとしてそれには共通デザインが不要な場合は以下のように
LayoutのRouteの中にネストせず外側に書けばOKです。
```typescript:index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';


// コンポーネントのインポート
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { About } from './components/About';
import { Contact } from './components/Contact';

const container = document.getElementById('app');
const root = createRoot(container!); 

root.render(
    <React.StrictMode>

    <BrowserRouter>
        
        <Routes>
            <Route path="/login" element={<Login />} />
            <Route path="/" element={<Layout />}>
                <Route path="/home" element={<Home />} />
                <Route path="/about" element={<About />} />
                <Route path="/contact" element={<Contact />} />
            </Route>
        </Routes>
        </BrowserRouter>
    </React.StrictMode>

);
```

以上です。
オフショア開発企業を選ぶ前に整理しておきたい前準備

こんにちは、ベトナムオフショア開発会社を運営しております、IDS Vietnam CEOの柴田達真と申します。

今回は、初めてオフショア開発の導入を検討している方に向けて「オフショア開発企業を選ぶ前に整理しておきたい前準備」についてお話しをさせて頂きます。

オフショア開発を始めるにあたって、オフショア開発企業選びはとても重要です。『オフショア開発企業選び=プロジェクトの成功の鍵』 と言っても過言ではありませんので、ぜひこれからオフショア開発の活用を検討しているかたはこちらの記事を読んで、オフショア開発企業選びの参考にして頂ければ幸いです。

【準備その①：自社アセスメントの実施】
まずはオフショア開発会社に委託をする前に、自社アセスメントを実施しましょう。まずは自社のことを整理することで、オフショア開発会社に求める要望や条件が整理できるため、オフショア開発企業を選ぶ判断基準を明確にすることができます。

・自社アセスメントの実施項目
┗プロジェクトの評価
→プロジェクトの複雑さ、開発期間、形式化されたドキュメントやナレッジがあるか

┗自社プロセスの評価
→開発プロセスや品質管理プロセスが自社でどれくらい定義されているか、アウトソースでも利用可能か

┗コミュニケーションとタイムゾーン
→オフショアチームとの円滑なコミュニケーションが行えるか（出張可否、ツール、チームビルディングのスキルなど）

┗コストとROI
→オフショア開発に掛けられるコスト（人件費、インフラ、出張なども含める）と期待されるROIが十分に得られそうか

リスク評価
→予期せぬ問題や遅延発生時のリスクマネジメント方法の確認

【準備その②：プロジェクト担当者のスキルを確認】
続いて、プロジェクト担当者のスキルを確認しておきましょう。同じシステム開発でも日本と海外では文化や仕事に対する考え方が異なります。マネジメント力や柔軟な対応力などが求められるシーンもある為、単なるエンジニアとしてのスキルだけでなくオフショア開発を活用する上でのビジネススキルがどの程度あるかを確認する必要があります。
例えば、担当者の設計スキルが足りない場合は、SE業務から委託できるオフショア開発会社に依頼する必要がありますし、コミュニケーションに不安があるということであれば日本人のサポートが得られるオフショア開発企業を選ぶと良いでしょう。
下記を参考にスキル確認をしておくと良いでしょう。

・プロジェクト担当者スキルの確認項目
┗該当業務に精通しているか
┗開発を一気通貫で行ったことが複数回あるか
┗グローバル思考で海外に興味があるか、海外出張が好きであるか
┗マネジメント経験があるか
┗オフショア開発の特性を理解しているか
┗リスク管理と問題解決能力があるか

【準備その③：オフショア開発委託先国の文化や特徴を知る】
日本における主要なオフショア開発先国は、中国・インド・ベトナム・ミャンマーなどが上げられます。国によって技術レベル・人件費・言語・文化・その時の政治的状況などが異なりますので、事前に確認し、自社に合うオフショア開発先国を選びましょう

・オフショア開発先国の特徴
中国、インド、ベトナム、ミャンマーそれぞれのエンジニア単価や特徴を簡単にお伝えします。

┗中国【時差：1時間　単価：BSE 85万円／PG 52万円】
→人口が多くIT技術者の数も多いオフショア開発大国です。漢字文化圏で日本語対応でき、技術力の高いエンジニアがいる為、大型案件や基盤系システム開発なども対応できるのが特徴です。
一方、人件費が高く、政治的リスクも考慮する必要があります。

┗インド【時差：3時間30分　単価：BSE 68万円／PG 52万円】
→オフショア開発の先駆けとなった国で、高いIT技術力や実績も豊富であることから大型案件への対応が可能です。 英語主体のサービス（日本語対応できるBrSEが少数）の為、プロジェクト担当者が英語が話せることが必須なります。 また人件費も割高です。

┗ベトナム【時差：2時間　単価：BSE 51万円／PG 40万円】
→安価な人件費と高い技術力に加えて親日国で日本語が話せる人が多く、オフショア開発先国として最も人気がある国です。
また、日本人と似た真面目で勤勉な国民性であることから日本人と相性がよく、仕事がしやすい国と言えます。国としてIT人材の育成に力を入れており、今後益々最近の技術を身に着けて若くて優秀なエンジニアが多く輩出されることが期待できます。

┗ミャンマー【時差：2時間30分　単価：BSE 49万円／PG 38万円】
オフショア開発の歴史は浅く、エンジニアの技術レベルは他国と比べ低い傾向があります。 またインフラ整備が不十分で、首都でも電気や電源が落ちることが日常的にあるため、スケジュールに気を付ける必要があります。 一方、開発コストが安く、親日家も多いので今後の成長に期待できるオフショア開発国と言えるでしょう。

まとめ
オフショア開発を成功させるには単純に日本語でのコミュニケーションがうまく取れたからというだけでなく、様々な観点から本当の意味で自社に合うオフショア開発企業を見つけることがオフショア開発成功への第一歩となります。

ベトナムオフショア開発ならスマラボ
ここまでお読み頂きありがとうございます。

本記事では書ききれないアドバイスやオフショア開発を開始するまでに確認しておいた方がよいことなど、お伝えできることがまだまだありますので、もっとお話しを聞きたいという方はぜひお気軽にお問い合わせくださいませ。
ベトナムオフショア開発サービススマラボ
https://sma-labo.jp/

セミナーなども定期的に開催しておりますので宜しければお気軽にご参加ください
セミナー情報：
https://sma-labo.jp/category/notice/seminar/

それではまたお会いしましょう
GitHub Actionsでキャッシュを利用してワークフローの時間を短縮する

GitHub ActionsでApp Distributionに配布する際、キャッシュが利用する事でワークフローの時間を短縮させる事ができたので紹介いたします。

## ■やりたい事
Podfileに変更がなかった場合には、キャッシュを利用してPod installの処理をスキップさせたい。

## ■作業手順
```yml
    - name: Cache Pods
      id: cache_id  //①IDを付与する。 1
      uses: actions/cache@v2
      with:
        path: Pods
        key: ${{ runner.os }}-${{ hashFiles('**/Podfile.lock') }}
    - name: Pod install
      if: steps.①のID名.outputs.cache-hit != 'true'　　//②付与したID名を入れる 2
      run: pod install
```

## ■結果
確認した所、Pod installがちゃんとスキップされていました。
これでPod installでかかっていた時間が削減されました！（私の場合は約3~5分）
![スクリーンショット 2023-08-18 17.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/b753b2f2-f48f-80c5-c23c-58ec79ced8ab.png)
chatGPTにディレクトリ構成図を表示させる

①以下の質問内容や構成図例をchatGPTに投げます
②さらに自分が表示してほしい図の
パスとディレクトリの内容を投げて依頼すればよいです。

●質問内容

今はVSCodeを使用していますが、pwdとlsで抽出したパスとディレクトリ内のファイルやフォルダを、以下に提示したディレクトリ構成図の例の様にルールに従いテキストベースで図式に変換できますか?

パス
[ec2-user@ip-123-45-67-890 testProject]$ pwd
/var/www/html/testProject

内容
[ec2-user@ip-123-45-67-890 testProject]$ ls
components           node_modules    package.json  README.md  store
ecosystem.config.js  nuxt.config.js  pages         static     yarn.lock

変換ルール
・ディレクトリと次のディレクトリは「パイプ」を使う
・ディレクトリと次のディレクトリでインデントする
・開いていないディレクトリは「+」を使う
・「.」拡張子のついているのはファイルで、
・「.」拡張子無しがディレクトリ

 /var
     |
     /www
         |
         /html
              |
             /testProject
                   |
                   + components
                   + node_modules
                    package.json
                    README.md
                  + store
                    ecosystem.config.js
                    nuxt.config.js
                  + pages
                  + static
                    yarn.lock
【人工知能学会全国大会2023参加報告】BERTからアートまで🎨

こんにちは。プロダクト開発本部の飯塚です。

6/6から6/9に開催された、[2023年度 人工知能学会全国大会（JSAI 2023）](https://www.ai-gakkai.or.jp/jsai2023/)を聴講しました。大会開催地は熊本（熊本城ホール）で、最新のAI研究✨とおいしい馬刺し🥩をインプットできた有意義な機会となりました。

聴講したものの中で興味を持った発表３つを紹介いたします。

## 泉 諒音、神野 健哉 - 画像生成モデルを用いたSentence-BERTの文ベクトルと調査

Sentence-BERTが生成する文ベクトルの性質や特徴を分析した研究です。Sentence-BERTはBERTをファインチューニングしたモデルで、入力された文に対して、その文の文脈をとらえた文ベクトル（分散表現）を生成します。この研究では「Sentence-BERTによる文ベクトルから画像を生成するデコーダモデル」を利用して文ベクトルを分析しており、ユニークで面白いと感じました。この研究では「青のタント」のような「色＋車種」形式のテキストとそれに対応する画像を用いていて、文ベクトルにおいて「色」を表している次元はどこかを探すアイデアや実験をまとめていました。実験の結果、文ベクトルの各次元の役割は完全に分断されているわけではないものの、各次元で表現される情報に違いがあることが確認されました。

自身が大学院でテキストの解きほぐし（distanglement）とスタイル変換に関して扱っていたことから、この研究に興味を持ちました。こういった研究（潜在表現の可視化）は説明可能なAIの開発に貢献する技術だと思うので、今後実務にAIが導入されるにあたって重要な役割を持つようになると思います。

## 瀬川 修 - 論文テキストを知識源とした情報推薦

キーワードから関連する論文タイトルや技術を提示する情報推薦に関する研究です。Sentence-BERTを用いて検索キーワードから「質問ベクトル」、論文タイトルと要旨から「論文ベクトル」を生成し、「質問ベクトル」に類似する「論文ベクトル」を探すことで、検索キーワードに対する情報推薦を行います。また、数語のキーワードによる「質問ベクトル」では不十分な検索結果が得られたことから、論文タイトルと要旨から生成した５００語程度のテキストにキーワードを拡張し、「質問ベクトル」を生成させました。この質問拡張の結果、比較的内容が妥当な論文がヒットしたそうです。また、この研究では論文の重要情報を抽出する際にXMLの構造情報を活用しています。

私はpdfやXML、HTMLの構造情報を使うことはドキュメントを効率的に処理することに対してとても有益であると思います。人間も文字の大きさや色、箇条書き、表などの単なる文字情報だけでなく、構造情報も駆使して、効率的にドキュメントを読み書きしています。そのため、その構造情報をAIが活用することも自然な発想であると思います。

※この研究ではデータセット作成において構造情報を活用しており、モデル自体に構造情報を学習させているわけではありません。

## 中川 裕志、武田 英明、大屋 雄裕、高橋 未玲 - アートにおいても敗北しつつある人間〜人の美意識もAIにハックされるのか？〜

生成AIの発展に伴い、AIのビジネスへの活用が活発化してきました。また、著作権・教育活用・悪用の問題点の整理も進んできています。このセッションではAI×アートをテーマに、倫理や権利、アートにおけるAIの存在について議論が行われました。

まずAIの倫理に関して、AIによってイラストレーターの仕事がなくなる！？といった話題について、「写真の登場」「産業革命」においても同じようなことが言われていたという話が興味深く感じました。新たなテクノロジーに人間が職を奪われることは、今に始まったことではない、とのことです。ただこれまでと異なるのは、AIによる影響力はインターネットを介して広範囲に、瞬く間に広まっていくということだと思います。AIの安全性を特に敏感に意識しなくてはならないと改めて感じました。

また、AIの権利については、AIを実際にビジネスに活用している私たちにとって、敏感に捉えるべきテーマだと感じます。AIの利用者、プロンプトエンジニアはプロデューサーの立場に似ているといった話に納得がいきました。プロデュースをアイデアととらえた場合、著作権法ではアイデアは保護対象とはならないので、プロデュースも保護対象とならない、となってしまうのだそうです。また、こういった問題は映画製作者に対しても考えられてきたことで、著作権法とは別に利益分配するシステムを設けることで解決されてきたそうです。インサイトテクノロジーにもAIを扱った製品（[Insight Governor](https://www.insight-tec.com/brand/insight-governor/)、[Insight Data Masking](https://www.insight-tec.com/products/idm/)）がありますが、それらは製品のシステムの一部にAIを組み込んでいる、といった形です。今後、「製品やその開発」におけるAIの機能が占める割合が拡大していくと、弊社においても AIの権利に関する議論をさらに活発に行う必要が出てくるかもしれません。今後もデータセットやモデルなどの著作権の侵害には細心の注意を払いたいと改めて思いました。

## おわりに

JSAI2023では、AIの最新技術のみならず、権利や倫理、安全性についても学ぶことができました。そして、何より、私自身もAIを活用した魅力的なテクノロジーを生み出せるようなエンジニアに成長したい😊と改めて思いました。
最後に、大会運営に携わった皆様に感謝申し上げます。
ユーザタイプの変更を管理者が把握するための設定

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート")
:::

# はじめに
New Relicを利用していてfull platformユーザを利用している場合、さまざまな情報を確認することができ非常に便利です。一方で管理者の立場からみた時には誰がfull platformユーザなのかを適切に管理したいという要望をよく聞きます。ユーザの利便性や詳細調査を行うという機運を邪魔することなく、管理者が適切にfull platformユーザを管理することができれば、よりNew Relicの活用を進めることができるようになります。

# どうする？
New Relicプラットフォームには[複数のユーザタイプ](https://docs.newrelic.com/jp/docs/accounts/accounts-billing/new-relic-one-user-management/user-type/#user-type-defined)が存在するのですが、ユーザを上位のタイプに変更する際に、管理者の承認を経て変更を実施するように設定することが可能です。
ユーザがユーザタイプを変更申請すると、管理者に変更依頼通知がメールで送信され、管理者が承認するとタイプ変更が完了するというフローになります。

New Relicを利用している際に以下の様な画面を見たことがある場合は、実施したい内容に即していないユーザタイプとなっているので、UI上の緑色の**Request access**ボタンをクリックして適切なユーザタイプに変更します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/aec6e09c-ac02-9120-5f3b-3dbdcf6f9327.png">


# 設定してみよう
1. [New Relicポータル](https://login.newrelic.com/)にログインします。
1. ポータル画面左下にあるユーザ名をクリックし、**Administration**メニューを選択します。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/b0a5b282-fb18-b6a1-9d3b-719fdaf6351b.png"></br>
1. **User management**メニューを選択し、UI上にある**歯車マーク**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/34ae9bbb-22f2-c2a7-e5c2-3aac480455a8.png)
1. 選択後、UIの右側から設定画面がスライドされるので、3つある**Automatic approval**トグルスイッチを無効化します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/5419796f-f1da-310c-6b1a-f2e515c225d2.png"></br>
1. 変更後、**Save**ボタンをクリックし、変更を反映させます。

:::note info
無効化したユーザタイプ変更の利用ケースが、ユーザによって発生された場合、管理者にメールという形で通知が届く様になります。
:::

**お疲れ様でした。これで設定は完了です!!**

# まとめ
New Relicを使い倒すための情報をこれからもどんどん発信していければと思います。また、New Relicを触ったことはないけれど、いろいろ触ってみたい興味をお持ちの方は、是非[こちら](https://newrelic.com/jp/sign-up-japan)から永久無料アカウントを作成して下さい。

:::note info
永久無料アカウントの詳細は[こちら](https://docs.newrelic.com/jp/docs/accounts/accounts-billing/account-setup/create-your-new-relic-account/)です。
:::
【躓き1文字】jQueryにCSSが当たってなさそうな時の解決方法

# 当該問題

コードはすべて同じなのに、UI表示が異なっていた。

1. Webアプリの本番環境でUIバグがある。
2. ローカルではこのUIバグは発生しない。

の時に確かめて欲しい!

# 解決

HTTPSになってなかっただけ:slight_smile:
ローカルだと動くんだけど、本番だと動かなかったりするよね。

### 変更前
~~~
http://code.jquery.com/ui/******/themes/hot-sneaks/jquery-ui.css
~~~

### 変更後
~~~
https://code.jquery.com/ui//******//themes/hot-sneaks/jquery-ui.css
~~~
シリアライズとデシリアライズってなに？

Rustの[勉強中](https://learn.microsoft.com/ja-jp/training/modules/rust-create-command-line-program/4-tasks-module)いきなり出てきた`シリアライズ`と`デシリアライズ`

**何それ!?**

調べてみても、わかりやすい用語の説明はあまりヒットせず、「~シリアライズのやり方~」的な内容しか出てこなかった...

この記事では、自分の解釈を自分なりにまとめてみました。
間違ってたら、ご指摘お願いします。

# シリアライズ(シリアル化)
シリアライズとは、超簡単にいうと
**複雑な物の単純化**
です。

私が調べたサイトでは
複雑なデータ構造やプログラムの実行状態などをバイトや文字列に変換すること。
と説明がされていました。

シリアライズの例として、私はベットを想像しました。

ベットって大きいし重いので運びづらいですよね。
でも、ベットを分解して部品をまとめることで運びやすくなります。
また、部品さえ揃っていれば別の場所でも同じ状態を再現できますよね。

**これがシリアライズです!!**

<strong>ベット(複雑なデータ)</strong>って扱いづらい...
でもシリアライズすることで、<strong>扱いやすい形(部品)</strong>に変換されます。
そうすることで、<strong>別の場所(違う環境)</strong>でも同じ状態を再現できる!

そういうことだったのかシリアライズ

# デシリアライズ(逆シリアル化)
デシリアライズは**再構成**です。
その名の通りシリアライズの逆ですね。

上の例を使うと、
まとめて送られてきた部品たちを組み立てて、ベットを再現するといった感じです。

片方を理解すると自然ともう片方も理解できるかもしれないですね。

そういうことだったのかデシリアライズ

# まとめ
超簡単に、自分の解釈をまとめてみました。
そのため、間違っている部分もあるかもしれないので、「へー」といった感じで見てください。

# 参考文献
[IT用語辞典 e-Words](https://e-words.jp/w/%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BA.html)
（Docker x Rails7.2.1 x Ruby3.2.5 x MySQL8）のミニマム構成のリポジトリを作成

## 更新情報

2023.08.28 [Rails 7.2.1 に対応しました。（マルチステージビルド化）](https://github.com/fooramu/docker-rails-quickly/commit/2808c6f2c4d4c6d0c5f2a53df64a9add2d46057f)
2023.01.17 [Rails 7.1.3 に対応しました。](https://github.com/fooramu/docker-rails-quickly/commit/9122719f30aff81233962ad9c331bce06c1102bf)

## 概要

![スクリーンショット 2023-08-18 10.47.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26033/fd12ca71-990b-c475-9fbc-14ee236d6345.png)

`docker-rails-quickly`

# リポジトリ

http://github.com/fooramu/docker-rails-quickly#docker-rails-quickly

## 概要

Railsを触るエンジニア用、また自分用の開発環境として「シンプル構成」なComposeファイルで仕上げたリポジトリを作成しました。

## コンテナ

Name | Description | ※
--- | --- | ---
db | MySQL 8 | Health check available (linked to `web`)
web | ruby 3.2.2, Rails 7.0.7 | `rails new --force --no-deps --database=mysql --minimal`

## コンセプト

- Railsの動作をチェックするために、これ以上開発環境構築で躓く必要はありません。
- git clone後の初期設定は必要ありません。
- 長い README を読む必要はありません。
- 謎のコンテナを起動する必要はありません。

## ポイント

- MySQL(db)コンテナが外部から接続Readyになった状態でRails(web)コンテナを起動させる
- Sidekiqや人気Gemなどをプリインストールさせない。
- テストコードやCICD考慮なし
- RailsのWelcomページが表示できればそれで良い。
- できる限り最新バージョンをお届けできるようにメンテしいく予定

## その他

過不足等あれば、すみませんが優しくツッコミを入れてくださいますようお願いいたします。
条件に一致するS3オブジェクトを一括で削除する方法

## 概要
Lambda関数を使って削除を行います。
まず、条件に一致したS3オブジェクトのみを列挙し、該当するオブジェクトを`S3.Client.delete_objects`メソッドで一括削除します。

## コード
```Python3
import boto3
import re
import os

BUCKET_NAME = 'test-s3-bucket' # 削除対象のS3バケット
PATTERN = r'^delete/target/prefix/2023080\d' # 削除対象のPrefix (正規表現)

# S3Client
s3_client = boto3.client('s3')

# 削除対象となるS3オブジェクトを列挙する
def list_objects_to_delete(bucket_name, pattern):
    response = s3_client.list_objects_v2(Bucket=bucket_name)
    objects_to_delete = []
    for obj in response.get('Contents', []):
        if re.match(pattern, obj['Key']):
            objects_to_delete.append({'Key': obj['Key']})
    return objects_to_delete

# objectsで与えられたS3オブジェクトを一括で削除する
def delete_objects(bucket_name, objects, should_delete):
    if should_delete != 'True':
        print("Delete flag is set to False. No object is deleted.")
        return
    if not objects:
        print("No objects to delete.")
        return
    response = s3_client.delete_objects(Bucket=bucket_name, Delete={'Objects': objects})
    if 'Deleted' in response:
        print(f"{len(response['Deleted'])} objects deleted.")
    if 'Errors' in response:
        print(f"{len(response['Errors'])} objects couldn't be deleted due to errors.")


def lambda_handler(event, context):
    # 安全装置
    should_delete = event.get('delete', 'False')

    # 対象となるオブジェクトをリストアップ
    objects_to_delete = list_objects_to_delete(BUCKET_NAME, PATTERN)

    if objects_to_delete:
        print("Objects to be deleted:")
        for obj in objects_to_delete:
            print(obj['Key'])
        delete_objects(BUCKET_NAME, objects_to_delete, should_delete)
    else:
        print("No objects matching the pattern to delete.")

    return {
        'statusCode': 200,
        'body': 'Objects deletion complete.'
    }
```

## 使い方
1. Lambda関数を上記コードで作成し、`BUCKET_NAME`と`PATTERN`に削除したいバケット名と正規表現パターンを設定する。
2. TestEventを作成して、以下のJSON文をリクエストに設定する。
    ```json
    {
      "delete": "False"
    }
    ```
3. 作成したTestEventを実行するとデバッグログに削除対象となるオブジェクト一覧が出力されるため、削除想定のものが表示されているか確認する。
4. TestEventに設定されている`delete`キーの値を`"True"`に設定して、再度Lambda関数を実行する。
    ```json
    {
      "delete": "True"
    }
    ```
5. 削除完了
テキストマイニングの基本処理_②ネットワーク分析

## この記事は何？
VSCodeで初めてのテキストマイニングに挑戦、その学習ログです。
「pythonによるテキストマイニング入門」（山内長承）が参考図書です

## 環境
VSCode

## 実践
#### テキストファイルを用意
・[安倍総理の会見](https://www.kantei.go.jp/jp/98_abe/statement/2020/0828kaiken.html)を引用
・テキスト部分をメモ帳アプリにコピー
・abe_sori_enzetsu.txtで保存
・適当なディレクトリに配置


#### ライブラリのインポート
```python
# パッケージをインストール
pip install igraph
pip install pycairo
```

```python
# 使用するライブラリをインポート
import re
import numpy as np
from collections import Counter
import MeCab
import itertools
from igraph import Graph, plot
```

#### ファイルの読み込み＆正規化
```python
minfreq = 0
m = MeCab.Tagger("-Ochasen")

# ファイルを読み込み、文を分割し空白を除去する関数
def readin(filename):
  with open(filename, "r", encoding="utf-8") as afile:
    whole_str = afile.read()
  # re.sub()関数で句点を置換、文を改行文字 "\\n" で分割
  sentenses = (re.sub("。", "。\n", whole_str)).splitlines()
  # 空白を削除し、文が空でない場合にそれを新しいリストに追加
  return [re.sub(" ", "", u) for u in sentenses if len(u)!=0]

# 先ほどの.txtファイルは以下に置いた
filename = "C:\\Users\\--ここは自分のPC参照--\\Documents\\nltk_data\\jeita\\jeita_aozora\\abe_sori_enzetsu.txt"
string = readin(filename)
```

#### 
```python
# 文単位で形態素解析し、名詞だけ抽出し、基本形を文ごとのリストにする
sentense_meishi_list = [ [v.split()[2] for v in m.parse(sentense).splitlines() if (len(v.split())>=3 and v.split()[3][:2] == "名詞" )] for sentense in string]
```

【解説】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/1ceae7fa-350f-b1f3-7010-45de85275809.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/9fa79d8d-cd76-74b6-f142-d2d11ac387f3.png)

```python
# 文ごとにペアリストを作る
doublets_list = [list(itertools.combinations(meishi_list, 2)) for meishi_list in sentense_meishi_list if len(meishi_list) >= 2]
all_doublets = []
# 文ごとのペアリストのリストをフラットなリストにする
for u in doublets_list:
    all_doublets.extend(u)

# 名詞ペアの頻度を数える
dcnt = Counter(all_doublets)

# 出現頻度順にソートした共起ペアを出力(上位30ペア)
print("pair frequency", sorted(dcnt.items(), key=lambda x: x[1], reverse=True)[:30])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/cc6ea853-3793-ffe4-a7df-42422551e9bf.png)

```python
# 名詞ペアの頻度辞書から、頻度が4以上のエントリだけを抜き出した辞書を作成
restricted_dcnt = dict(((k, dcnt[k]) for k in dcnt.keys() if dcnt[k] >= minfreq))
charedges = restricted_dcnt.keys()
vertices = list(set( [v[0] for v in charedges] + [v[1] for v in charedges] ))

# charedgesは(["名詞","名詞"])の形なのでvertid(数字)
edges = [(vertices.index(u[0]), vertices.index(u[1])) for u in charedges]

g = Graph(vertex_attrs={"label": vertices, "name": vertices}, edges=edges, directed=False)

plot(g, vertex_size=20, bbox=(800, 800), vertex_color="white", fontname="IPAGothic")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/58ffc9c0-601e-0d92-a9a0-b92268cffb10.png)

※
文字化けしたが、直し方が分からない…
いつか[この方の記事](https://web-tweets.com/python/igraph-font/)などを参考に直す
gfortran 移植メモ

レガシーコードを gfortran でコンパイルして蹴られたところのメモ。

## 負の冪乗

```
Error: Raising a negative REAL at (1) to a REAL power is prohibited
```

負値を実数で冪乗することは禁止だと言っています。

（以前ここに余計なことを書いたが訂正。少なくとも Fortran 2003 には禁止規定があります（§7.1.8）。 ）

ケースでは、`(-12.0)**X` というようなコードがあって、`X` は実数型とはいえ整数値の定数がありました。他で `X` が使われていない保証ができれば整数型に変えるのですが、面倒だったので、`-(12.0**X)` に置き換えました。

## １行が長過ぎる

```
Error: Symbol 'x' at (1) has no IMPLICIT type
```

読んでみると `x` などという変数はないのですが、 `x` で始まる変数がありました。よく見ると１行が132文字（F95§3.3.1）を超えていて、先頭１文字だけが認識されていたのです。`&` を使って行を折り返して解決。

```
エラー: Unterminated character constant beginning at (1)
```

文字列が途中で切れている場合はこうなります。

## DATA 文の初期値と配列長が不整合

```
Error: DATA statement at (1) has more variables than values
```

DATA 文の変数（初期化項目並び）と値（初期値表現並び）の数は同じでなければなりません（F95§5.2.9に明示規定あり）。大きな配列を宣言して、DATA 文で与える値が少ないと上のメッセージが出ます（gfortran以外の大抵のコンパイラでは不足する配列要素が不定値になるようです）。逆に値が多すぎると「more values than variables」というメッセージが出ます。

「more variables than values」の場合は、DATA文にダミーの初期値を書き込むか、配列を小さくすることで解決できます。配列の大きさを無闇に変えるとメモリレイアウトの変化などによる問題が評価しきれないので、ダミーの初期値を埋め込むほうが無難でしょう。

```Fortran
REAL ARY(100)
DATA ARY/0., 1., 2., 3./
```
とあったら（たとえばダミー値 `999.` を追加するなら）

```Fortran
REAL ARY(100)
DATA ARY/0., 1., 2., 3., 96*999./
```
のようにすれば解決です。値を数えるのが面倒だったら、`1*999.` から増やしていってメッセージが変わったところで止めればよいです。

ちょっとやっかいなのが、配列 `ARY` が EQUIVALENCE 文や COMMON ブロックなどを使って他の配列とオーバーラップしている場合です。この場合はオーバーラップ先で DATA 文を使っていると衝突してしまいます（gfortran はエラーにしてくれるのでエライです）。仕方がないので数を数えて必要なだけダミー値を設定します。

```Fortran
REAL ARY(100), OTHER(100)
EQUIVALENCE(ARY(51), OTHER(1))
DATA ARY/0., 1., 2., 3., 46*999./
```


## 整数型変数に文字を代入

```
      KSY= 'X'                                                          
           1
Error: Can't convert CHARACTER(1) to INTEGER(4) at (1)
```
整数型変数 `KSY` はこの直後でサブルーチン引数としてだけ使われます。おそらくかつてはホレリス定数 `1HX` をサブルーチン引数に使っていたのを書き換えたのでしょう。

Intel Fortran では字数が4の倍数ではない文字型値を整数変数に代入すると、あたかも4文字の文字型変数に代入したかのように右に空白を補ってからtransferしたかのように挙動します。つまり

```Fortran
KSY=TRANSFER('X   ', KSY)
```

とすれば、gfortran でも通るし、Intel Fortran でも従来通りの挙動になります。

## NAMELISTを実行文の間に書く

やりたいたいことはわかるのです。NAMELIST は所詮 READ 文の入出力対象を列挙しているだけなので、当該 READ 文の近くにあった方が読みやすい。が、 gfortran では蹴られます。

対処は簡単で NAMELIST 文を最初の実行文の前に移すだけです。

## 警告だから放置したもの

整数と実数を同一視する警告がほうぼうに見られました。

* DO ループの端を実数にしてはいけません
* 配列添字を実数にしてはいけません
* 実数型引数に整数を与えてはいけません

最後のはヤバイはずですが、どう変えるべきかは慎重に読む必要があります。
Javaアプリを手軽にリアルタイムプロファイリングする

# 概要
Javaを使ったアプリケーションを運用する場合、JVMやGCと付き合っていく必要があります。それらの情報を取得しプロファイリングするツールとしてJava Flight Recorder（JFR）がありますが、New Relicでもその結果を可視化して分析することができます。

New Relic APMエージェントでは、このJFRを使ったリアルタイムのプロファイリングをアプリケーションの再起動なしに有効化・無効化して気軽に利用できます。これにより、例えば本番環境で何かしらの性能問題が発生した場合であっても調査のために一時的にプロファイリングすることができます。

:::note info
このアップデートの詳細はこちら
[New Relic アップデート(2023年3月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202303)
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update)
:::

:::note info
無料のアカウントで試してみよう！
[New Relic フリープランで始めるオブザーバビリティ！
](https://qiita.com/ktst79/items/5ee74b34e6adb8a7a6fa)
:::

それでは早速JFRによるリアルタイムプロファイリングを試してみましょう。

# 手順
手順は非常に簡単で、UI上からJFRによるリアルタイムプロファイリング機能を有効にするだけです。
New Relicログイン後、「APM & Services」メニューから、New Relic APMの画面で対象のアプリケーションを選択します。
続いて、APMのメニューにある「Application」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/e2a29e50-6aa7-293f-890a-1348a3f689c2.png)

Applicationメニューでは、APMエージェントの設定の一部を画面上から実施できます。
まずは、「Enable server-side configuration」をONにして、設定がエージェントに反映されるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/479d36b8-606a-1c28-0dbf-72b29da506bb.png)

続いて、「Enable Java flight recorder」をONにして、JFRによるリアルタイムプロファイリングを開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/3da83beb-3bb7-0410-a3f9-46005feefcd1.png)

設定はこれで完了です。
設定内容が稼働中のアプリケーションで動作するAPMエージェントに反映され、プロファイラーが稼働し始めます。

画面上で確認してみましょう。
APMの画面の「Realtime Profiling Java」メニューで収集したデータが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/0aaeadb3-12a6-badc-cfd6-063c22cf33a7.png)

JVM毎にJFRで収集したデータが時系列で表示されます。今回の例ではJVMが1つですが、アプリケーションがスケールアウト構成の場合はホストやコンテナ毎にJVMが表示されます。
スクリーンショット上では特に問題は見受けられませんが、CPU使用率やヒープ使用率が上昇している場合はWarning（黄色）やCritical（赤）でハイライトされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/401f2a74-85f1-d0d3-85a7-dc3641af768a.png)

特定の時間帯をクリックすると、その時間帯のプロファイリング結果が確認できます。
具体的には、コールスタックのメソッド毎の実行時間やJVMのCPU使用率、GCの発生状況などです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535230/4034959e-dba4-0402-e2cb-fa666c7dedf8.png)

稼働中のアプリでもUIで設定するだけでリアルタイムプロファイリングができることが確認できました。
調査が終了した場合は、冒頭の設定と同じ流れでJFRによるリアルタイムプロファイリングを無効にできます。

# まとめ
今回、JFRによるJavaアプリケーションのリアルタイムプロファイリングが簡単にできることをご紹介しました。
本番環境などで性能問題が発生した場合にはアプリの再起動せずに確認できるのでお試しください。

:::note info
このアップデートの詳細はこちら
[New Relic アップデート(2023年3月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202303)
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update)
:::

:::note info
無料のアカウントで試してみよう！
[New Relic フリープランで始めるオブザーバビリティ！
](https://qiita.com/ktst79/items/5ee74b34e6adb8a7a6fa)
:::
Pythonでラムダ式を使う

Pythonでラムダ式の使い方をまとめました
※ラムダ式は英語で"lambda"と表記されますが、AWSのLambdaとは異なります

Pythonのラムダ式は無名関数で、通常はdefで関数名を定義しますが
ラムダ式は引数と式などで構成されます

具体的にコードの違いを見てみましょう

defの場合
```python
def add_function(x, y):
    return x + y
```

ラムダ式の場合
```python
add_value = lambda x, y: x + y
```

# メリット
+ シンプル
 1行で処理が記載できるので簡潔にコードを書けます
 filter()などの高階関数（関数を引数として受け取る関数）と組み合わせるとよりコードが短く書けます

+ 関数(メソッド)が減らせる
 先ほど示したようにdefで定義してメソッド化する手間が減ります

# 高階関数を使用したラムダ式
+ filter
配列の数字の中から偶数の数字を抽出する処理
```python
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
even_list = list(even_numbers)
print(even_list)
# 出力: [2, 4, 6, 8, 10]
```

+ map
配列の数字にプラス1する処理
```python
numbers = [1, 2, 3, 4, 5]
add_numbers = map(lambda x: x + 1, numbers)
add_list = list(add_numbers)
print(add_list)
# 出力: [2, 3, 4, 5, 6]
```
+ reduce
配列の数字を全て掛け算する処理
```python
from functools import reduce

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)
# 出力: 120
```

# ラムダ式の使い方
冒頭で述べた通りラムダ式は無名関数のため、変数や式を用いて関数を作成できます
例を示すと
```python
add_number = lambda x, y : x + y
print(add_number(4, 6))
# 出力: 10
```
2つの変数を足す関数を定義しておきます
add_numberが呼ばれると2つの引数を足し合わせる処理が実行されます

このように任意に引数を設定する場合は、引数の順番が大事で順序を入れ替えることはできません。
順序を入れ替えたい場合はどのようにしたら良いでしょうか？

POSシステムのような決済システムでの1例で売値や割引率、消費税を考慮して販売価格を計算する処理を作成してみました
```python
discounted_price = lambda price, discount = 0.1, vat = 0.02 : price * (1 - discount) * (1 + vat)
print(discounted_price(1000, vat=0.04, discount=0.3))
# 出力: 728.0
```
vat=0.04, discount=0.3、このようにキーワード引数とすることで
ラムダ式の中にdiscount = 0.1, vat = 0.02を定義していますが引数の値で上書きして計算することができます

ラムダ式では、price→discount→vatの順で値が定義されていますが
2行目のdiscounted_priceを呼び出している時は、price→vat→discountの順で設定していますが、想定通りに処理されています


## for文(リスト内包表記)
```python
numbers = [1, 2, 3, 4, 5]
add_numbers = [(lambda x: x + 2)(num) for num in numbers]
print(add_numbers)
# 出力: [2, 4, 6, 8, 10]
```
ラムダ式の中でfor文を使用した例です
リスト内包表記をラムダに組み込むことは可能です
人によっては可読性が落ちるため、ラムダの処理とfor文の処理は分けて書いた方が保守しやすいかもしれません


## 三項式
```python
calc = lambda x, y, is_add: x + y if is_add else x - y
result = calc(10, 5, True)
print(result)
# 出力: 15
```
三項式もラムダ式で使用できます
三項式の条件が複雑な場合は処理を分けて書いた方が可読性が高まります


# まとめ
ラムダ式を使用するとコードを簡潔に短く書くことができ、Pythonの特徴のシンプルさを体現できます
また、後半のように可読性は問題となってくるためチームの状況に応じて使用することが推奨されます
ラムダ式と相性が良いのはfilter関数のような高階関数だと思います

自分は高階関数はラムダ式で使いますが、三項式やfor文は分けて書いています


# 備考
Python公式のラムダ式についてコチラ

https://docs.python.org/ja/3/reference/expressions.html#lambda

Python公式のスタイルガイド

https://peps.python.org/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds

コードの可読性について参考になります
Emacsで文字コードを変換する方法

毎回検索していて嫌になったのでここにメモする。

1. Emacsでファイルを開く
2. C-x RET F coding RET
3. C-x C-sで上書き保存

参考：https://emacsdocs.org/docs/emacs/File-Name-Coding

utf-8にしたい場合は、
① Ctrlボタンを押しながら「x」キー
② Enterキー
③ 「f」キー
④ 「utf-8」と入力する
⑤ Enterキー

---
メモ：codingリストは以下コマンドで表示可能
M-x list-coding-systems

メモ：codingに指定する名称が分からないときは、分かるところまで入力してEnterを押すと候補がリストアップされる

(例)「S」を入力した後にEnterした場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/50f19012-c15f-5ef2-de7b-bd9fc4a49f74.png)