OmniAICreator/Qiita-1.07M huggingface dataset:
APIを使って天気情報を取得する

## 今回使うAPIはこれ

https://openweathermap.org/

OpenWeatherです。
現在の天気や、天気予報、過去の天気、降水マップなど様々な情報を取得できます。

無料枠でも、1000件/日まで利用できることもあり、お試し利用するにはちょうど良いです。
日本の情報だけで良い場合は、国産サービスを選択するのもいいと思います。

## 利用方法

### アカウント登録〜APIキー取得

https://openweathermap.org/api
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282054/ca28fe9f-e4be-b9fc-d692-918cd3ff7c92.png)

この辺りから、アカウント登録を行い、APIキーを取得しましょう。

### 現在の天気を取得してみる

https://openweathermap.org/current

```how to
https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}
```

今回は、ハワイの気温を`units`に`metric`を設定して、馴染みのある温度表記で取得しています。

```sh
% curl "https://api.openweathermap.org/data/2.5/weather?lat=21.2762123&lon=-157.8317062&units=metric&appid=xxxxxxxxxxxx"
{"coord":{"lon":-157.8317,"lat":21.2762},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02n"}],"base":"stations","main":{"temp":21.72,"feels_like":22.25,"temp_min":20.69,"temp_max":22.19,"pressure":1015,"humidity":88},"visibility":10000,"wind":{"speed":2.57,"deg":10},"clouds":{"all":20},"dt":1669723467,"sys":{"type":1,"id":7878,"country":"US","sunrise":1669740686,"sunset":1669780106},"timezone":-36000,"id":5850943,"name":"Maunalani Heights","cod":200}
```

データを展開すると。
```js
{
  "coord": {
    "lon": -157.8317,
    "lat": 21.2762
  },
  "weather": [
    {
      "id": 801,
      "main": "Clouds",
      "description": "few clouds",
      "icon": "02n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 21.72,
    "feels_like": 22.25,
    "temp_min": 20.69,
    "temp_max": 22.19,
    "pressure": 1015,
    "humidity": 88
  },
  "visibility": 10000,
  "wind": {
    "speed": 2.57,
    "deg": 10
  },
  "clouds": {
    "all": 20
  },
  "dt": 1669723467,
  "sys": {
    "type": 1,
    "id": 7878,
    "country": "US",
    "sunrise": 1669740686,
    "sunset": 1669780106
  },
  "timezone": -36000,
  "id": 5850943,
  "name": "Maunalani Heights",
  "cod": 200
}
```

めちゃくちゃ簡単です。

lat/lonは、Google Mapから取得しても良いですし、この辺りの、ジオコーディングAPIを利用して住所から緯度経度に変換してもよさそうです。

https://blog.geolonia.com/2020/06/01/community-geocoder.html

## 最後に

APIは楽しい！
[React×Storybook]プリミティブ型でないpropsの指定をしたいが、controlsが表示されない場合の対処法

# 状況
create-react-app で構築したReactのプロジェクトにStorybookを導入し、既存のコンポーネント用にStoryを追加したが、controlsが表示されない。

ブラウザでStorybookの画面を見ると、“This story is not configured to handle controls.” というメッセージが表示されている。

![Something went wrong](https://user-images.githubusercontent.com/48222/94113711-99853b00-fe47-11ea-8d34-3ca7ec3f7046.jpg)

- 対象のコンポーネント

```react:ShopItem.tsx
export type Shop = {
  location: Location;
  name: string;
  photo: string;
  rating: number;
};

export type Location = {
  lat: number;
  lng: number;
};

export type Props = {
  shop: Shop;
  currentLocation: Location;
};

const ShopItem = ({ shop, currentLocation }: Props) => {
  return (
  <>省略<>
  );
};
export default ShopItem;
```

# 解決方法

storiesファイルで、コンポーネントに実際に渡ってくるpropsの型を `args` に指定し、さらに `args` にサンプル値を指定する。

```react:ShopItem.stories.tsx
import { ComponentMeta, ComponentStory } from '@storybook/react';
import ShopItem, { Props } from './ShopItem';

export default {
  title: 'Components/ShopItem',
  component: ShopItem,
} as ComponentMeta<typeof ShopItem>;

export const StoryShopItem = (args: Props) => <ShopItem {...args} />;

StoryShopItem.args = {
  shop: {
    location: { lat: 123, lng: 456 },
    name: 'name',
    photo: 'https://placehold.jp/450x150.png',
    rating: 3,
  },
  currentLocation: {
    lat: 123,
    lng: 456,
  },
};
```

Storybookでは `args` に指定した値がデフォルトで表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1481264/9449f22e-2a4b-431e-6dad-fbabfe1d641f.png)

それぞれ値を変更することも可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1481264/e03890a0-8b3e-fc2f-1326-75b7c9dc37d8.png)

# おわりに

弊社では勉強会の一環でオープンソースのとんかつアプリを開発しています。
一緒に開発していただける方、お待ちしております。

https://github.com/oz-sysb/study-202207
Blazorで特定のページだけSignalRを繋ぎたい

この記事は、私の試行錯誤の記録であり、だいぶ良いところまで行ってるものの、道半ばです。
より良いアイデア・ドキュメント等ご存知の方がいらっしゃいましたら、教えてほしいです。

# はじめに

Blazor Serverで作ったページを開くと、ブラウザとサーバが自動でSignalRで接続される。
ページ遷移等におけるUIの変更がサーバ側で処理され、DOMの差分がこのSignalRの回線を通してブラウザに届くことで、すごいいい感じにUIが更新される。

しかし！タブブラウザとかでタブが休眠すると、SignalRが切れ、再接続がイマイチだったりして、いいところばっかじゃない。

動的な画面更新とか、フォームとかはSignalR繋がっても良いけど、そうでないページはSignalR繋がないことはできるのか？という話。

https://qiita.com/jsakamoto/items/41bc81b07dce57680772

↑上記の記事を参考にしました。この記事では、SignalRが完全に使えない状況を想定していて、すべてのページを静的にしている。
今回想定しているのは、**SignalR使えなくはないけど、必要に応じてのみ使いたい**状況。

# とりあえずの解決

まず、Blazor Serverのプロジェクトを新規作成しましょう。一応.Net6のテンプレートで説明を進めます。まぁ、.Net7も大体いっしょ。

修正場所は、以下の2点。
まず、SignalRの接続をつかさどっている大元、Pages/_Layout.cshtmlの下の方にあるJavaScriptの部分。これを、必要な時のみ読み込ませる（レンダリングする）ようにすればよい。

```html
<script src="_framework/blazor.server.js"></script>
```

次に、Pages/_Host.cshtmlの、コンポーネントのレンダリング開始場所。このrender-modeを調整することで、サーバのふるまいを調整する。
```html
<component type="typeof(App)" render-mode="ServerPrerendered" />
```

## ①_Host.cshtmlの修正

リクエストの時に呼び出される順番は、_Hostが先なので、まずこっちから修正する。
```c#
@{
    Layout = "_Layout";

    var mode = RenderMode.Static;
    var path = Request.Path.Value!;
    var page = new[] { "/create", "/edit", "/delete" };
    if (page.Any(t => path.Contains(t, StringComparison.OrdinalIgnoreCase))) mode = RenderMode.Server;

    ViewBag.RenderMode = mode;
}

<component type="typeof(App)" render-mode="@mode" />
```

リクエストされたURLによって、render-modeを変えるようにした。

render-modeについては以下の通り。
- RenderMode.ServerPrerendered
    - 先にサーバでレンダリングし、ブラウザに完成したHtmlを送る。
    ブラウザはそれを表示した後にSignalR接続を開始し、接続後もう一度レンダリングする。以後、UIの変更はSignalR接続により処理される。つまり**初回接続時は、2回レンダリングされる。**
    **（JavaScriptを実行できない）検索サイトのクローラとかでも、ページのコンテンツを取得できる利点がある。**
- RenderMode.Static
    - 先にサーバでレンダリングし、ブラウザに完成したHtmlを送る。
    ブラウザはそれを表示した後SignalR接続を開始するが、接続を介してのレンダリングはしない。SignalR接続されるので、接続を介してのレンダリングはしないものの、接続が切れたりすると再接続が求められる。
- RenderMode.Server
    - 先にレンダリングしない。ブラウザには、テンプレート部分だけ送られる。
    ブラウザはそれを表示した後SignalR接続を開始し、コンテンツ部分をレンダリングする。レンダリングは1回。
**JavaScriptが動かないと、画面にテンプレート部分しか表示されない。**

今回の例では、普通のページをRenderMode.Staticにし、フォームのページをRenderMode.Serverにしている。
フォームのページは、SignalR接続しなきゃ機能を果たさないし、検索エンジン対策する必要もないので、ServerPrerenderedではなくServerにしている。レンダリング1回になるので、その方が都合がよい。

ここでrender-modeをどれにしても、SignalRは接続される。Staticにしたときは、接続しないようにしたい。
そこで、modeをViewBagに突っ込んで、次へ…

## ②_Layout.cshtmlの修正

```html
@if (ViewBag.RenderMode != RenderMode.Static)
{
    <script src="_framework/blazor.server.js"></script>
}
```
このJavaScriptさえ読み込ませなければ、SignalRは接続されない。そこで、ViewBagの中身を確認して、Staticの時にそもそもこの行をレンダリングしないようにする。
これでSignalRが接続されなくなって、うれしい！


# 現状の問題

上述した方法だと、問題がある。

- RenderModeがStaticのページのみを遷移しているとき…
    - 遷移時に毎回サーバにリクエストされて完璧。
- 一旦Staticではないページ（フォームとか）に入っちゃうと…
    - そこでSignalR接続され、以後Staticであってほしいページに戻っても、回線を使ってコンポーネント以下でUIが更新されるようになってしまう。

NavigationManagerで強制移動してリロードさせちゃえば、またStaticに戻るんだけど、すべてのリンクでやるのはめんどくさい…
Staticなページがメインなサイト（管理者しかフォームのページに行かない…）とかなら、とりあえずこれで良いかな…
個人アプリをリリースした話

## はじめに

今年、6月に初めて、iOSアプリとAndroidアプリをリリースしました。
そこまでに実施したことを、箇条書きで紹介します。

## やったこと

### アプリイメージの想像

何か作りたいと、もやもや考えていた時に、自分が欲しいものってなんだろう？というところから、着想しました。

### Figmaでのデザイン作成

いきなりアプリ開発に入るよりも、まずは、一度やりたいことを整理してから作成した方が良いと考え、Figmaで整理しました。

これをやっていたから、アプリ開発期間を短くできたのではないかと考えています。

### Flutterでアプリ作成

せっかくなら、スマホ全般で利用できるアプリにしたかったので、Flutterを採用しました。

アプリ開発中は、シミュレータ、実機を利用して操作感を念入りに確認して進めました。

### Test flight公開

５割程度完成したところで、テストフライトに公開しました。
公開といっても利用者は私だけなのですが。。。

### App store申請/Google Play store申請

私のデバイスがiPhoneだったので、App Storeから申請し、後からGoogle Play Storeに申請をかけました。


### 反省

- 多言語化対応は先に入れておくのが良い。
- 端末切り替えなどを考慮して、利用せずとも先にfirebaseなどを導入しておくのが良い。
- アプリリリース後も開発モチベーションが保てるものを作る方が良い。

## 最後に

アプリを作ろうと思ったきっかけや、機能の紹介は note に記載しましたのでそちらを参照ください。

https://note.com/shohei_yamamoto/n/nc525cfc2e4ae

開発までのツイートまとめはこちら

https://qiita.com/shohei-y/items/eec75518d753399f3e69
ChromebookとZenn CLIで記事を書く方法

ChromebookとZenn CLIで記事を書く方法を紹介します。

※この記事はまだ未解決の問題を残しています。



## 準備　その1　GitHub連携

ZennとGitHubを連携させておきます。

**ZennとGitHubを連携させる方法 - Qiita https://qiita.com/akiba_burari/items/2423d284bab666e01f45**

https://qiita.com/akiba_burari/items/2423d284bab666e01f45

GitHubにZennの共有リポジトリを作り、アドレスをメモしておきます。

## 準備　その2　Zenn CLIインストール

ChromebookにZenn CLIをインストールしておきます。

**ChromebookにZenn CLIをインストールする方法 - Qiita https://qiita.com/akiba_burari/items/23b1b3668279618089b5**

https://qiita.com/akiba_burari/items/23b1b3668279618089b5


## 準備  その3 ディレクトリを確認

Zenn CLIで記事を書く前に、Zenn CLIのフォルダ（ディレクトリ）を確認しておきます。

作成する記事はarticles内に保存します。

.
└─ articles
   ├── example-article1.md
   └── example-article2.md









## 記事ファイルを作成する

ターミナルから「zenn」ディレクトリ（※Zennのファイルがすべて入っているディレクトリ）に移動します。

cd zenn

以下のコマンドでmarkdownファイルを作成します。実行すると、articles/ランダムなslug.mdというファイルが作成されます。

```
$ npx zenn new:article
 ```


例：articles/4e63b5fc8e6a2b.md



##  作成したファイルを確認

「articles」ディレクトリに移動し、ファイルがあるかどうか確認します。

```
cd articles
```

作成したファイルを確認

```
ls
```

ここで先ほど作成したファイル「articles/4e63b5fc8e6a2b.md」が表示されていればOKです。




## 記事を書くためのエディタを決める

 作成したmdファイルを編集するためにエディタが必要になります。

 Visual Studio Codeも利用できますが、Chromebookの場合、日本語が記述できません。

Emacsは日本語切り替えができるようですが詳しいことはまだ調べていません。

自分はとりあえずターミナル上で日本語入力できるようにしてあったので、「nano」を使うことにしました。

※インストールコマンド

```
sudo apt install nano
```


## 記事を書く

作成したファイルに記事を書いていきます。

以下、「articles」ディレクトリに移動してコマンドを入力


**＜Visual Studio Codeでファイルを開く＞**

code 6b4aed7c6f1051.md

**＜Emacsでファイルを開く＞**

emacs  6b4aed7c6f1051.md

**＜nanoでファイルを開く＞**

nano 6b4aed7c6f1051.md


### 記事の中身

---
title: "" # 記事のタイトル
emoji: "😸" # アイキャッチとして使われる絵文字（1文字だけ）
type: "tech" # tech: 技術記事 / idea: アイデア記事
topics: [] # タグ。["markdown", "rust", "aws"]のように指定する
published: true # 公開設定（falseにすると下書き）
---
ここから本文を書く


## プレビューする

記事をプレビューするには、

記事を開いたまま、新しいタブを開き、

ターミナル上でコマンドを実行します。

```
$ npx zenn preview    #プレビュー開始
```

ブラウザが自動で立ち上がるはずですが、

Chromebookでは自動でブラウザが立ち上がりません。

そこであらかじめChromeブラウザを自分で開いておき、

```
localhost:8000
```

とブラウザのバーに直接入力しておきます。

プレビューのコマンドを入力してから、しばらくすると、

プレビューが表示されます。



## 未解決の問題

プレビューは一応表示されるのですが、

記事の内容が全く表示されません。

ターミナル上（※プレビューらしきものが表示されている）では「タイトル名」だけ表示されているのが確認できます。

Chromeブラウザ上で「Zenn CLI」の画面が表示されるものの、

トップ画面だけで、自分の記事は表示されません。

この問題はまだ未解決で、今のところどうしていいか分かりません。

分かり次第、記事を修正する予定です。



## 記事を保存して閉じる

最後に記事を保存して閉じます。

nanoの場合は、

ctl + O #保存

ctl + X  #閉じる

で記事を保存し、ターミナルに戻ることができます。


## 参考サイト 一覧

Zenn CLIで記事・本を管理する方法 https://zenn.dev/zenn/articles/zenn-cli-guide

ローカルリポジトリをリモートにpushするまで - Qiita https://qiita.com/sayama0402/items/9afbb519d97327b9f05c

コマンドラインからVS Codeでファイルやフォルダを開く - Qiita https://qiita.com/1natsu172/items/b951aa33451dad36bd7c
GitHub Actions Workflow ubuntu-latest が 22.04 に

https://github.blog/changelog/2022-08-09-github-actions-ubuntu-22-04-is-now-generally-available-on-github-hosted-runners

GitHub の Actions を使って ubuntu 用のリリースビルドを作る時、下のような workflow を作ると思いますが、ubuntu-latest が示すバージョンが 20.04 から 22.04 に変更になったようです。



```main.yaml
name: Build

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - run: sudo apt -y update
      - run: sudo apt -y upgrade
      - run: sudo apt -y install build-essential
以下略
```

C++ のライブラリを作っていたのですが見事にどハマりしました。



解決策は以下の２つのどちらかだと思います。

* ubuntu のバージョンを固定する
```
runs-on: ubuntu-latest
↓
runs-on: ubuntu-20.04
```

* 利用側の環境を latest に保つ

使っている人は一応チェックしてみましょう。
Kotlinのwhen式

Kotlinのはwhen式というものが用意されている。
when式とはJavaでいうswitch 〜 case文のようなものである。

        //Java
        switch (式){
            case 結果1:
                式の値が結果1の時の処理
                break;
            case 結果2:
                式の値が結果2の時の処理
                break;
            default:
                上のどれにも当てはまらない場合の処理
                break;
        }

        //Kotlin
        when(条件式){
            条件式の結果1 -> 結果が1の時の処理
            条件式の結果2 -> 結果が2の時の処理
            else -> 上のどれにも当てはまらない場合の処理
        }

Javaのswitch文との違いは以下の通りである。
　・Javaでは「switch 」だったがKotlinでは「when」になった。
　・Javaでは「case:」だったがKotlinでは「->」になった。
　・Kotlinは各条件の処理の終わりにbreakを記述する必要がない。
　・Javaでは条件に当てはまらないものを処理する場合、「default」と記載するが、
　　Kotlinでは「else」を記載する。
Ubuntu 22.04 - Nginx インストール

## 環境
Ubuntu 22.04 LTS
Nginx 1.18.0
## 設定
### Nginx インストール
```
$ sudo apt update
$ sudo apt install nginx
```
### Firewall の設定
Firewall の設定を忘れることなかれ。`ufw`が認識しているアプリケーション構成を確認しておく。
```
$ sudo ufw app list
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
```
とりあえず、Full で許可する。
```
$ sudo ufw allow 'Nginx Full'
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)
```
### Web サーバの確認
`active (running)`になっていればOK
```
$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-11-29 11:08:00 UTC; 4min 12s ago
       Docs: man:nginx(8)
    Process: 3618 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 3620 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 3738 (nginx)
      Tasks: 2 (limit: 1033)
     Memory: 4.1M
        CPU: 30ms
     CGroup: /system.slice/nginx.service
             tq3738 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             mq3741 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
```
### Web ブラウザからアクセス
http://X.X.X.X:80 をたたいてみる。次のように表示されたら完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263451/adf99f29-914f-9014-ca12-4d7bdd34e83a.png)
### Nginx のバージョン
確認しておく。んー。最新じゃない。最新にする方法は次の記事で。
```
$ nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
```
プロジェクトを進める上でやっておくこと

こんにちは、株式会社HRBrainでエンジニアをしているしっぽくん（[@shippo_kunn](https://twitter.com/shippo_kunn)）です。
この記事は[HRBrainのAdvent Calender](https://qiita.com/advent-calendar/2022/hrbrain)の3日目の記事です。

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

最近はいくつかのプロダクトを跨いだチームで開発をしています。日頃の仕事内容については先日インタビュー記事を書いていただいたので興味ある方は下記を参照してください。

https://www.wantedly.com/companies/hrbrain/post_articles/445253

# はじめに

今回は先月PjM（Project Manager）にトライしてみた時の反省点や良かったことを箇条書きでまとめてみました。手前味噌ではありますが何かの参考になれば幸いです。

:::note warn
個人の振り返りに基づいた記事であるという前提の上でご覧ください。
:::

## この記事の対象者

- プロジェクトを初めて管理する人

## 前提

弊社では下記のツールを用いて開発をしています。適宜ご自身の環境に読み替えてください。
- JIRA: チケット管理
- GitHub: コード管理
- Notion: 仕様やドキュメント管理
- Figma: デザイン管理
- Slack: チャットツール
- Autify: E2Eテストツール

# プロジェクト開始

## 事前に危険性を洗い出すこと

- 有識者とプロジェクトについて知見を交わし、デグレ対応にどのくらい時間が必要なのかを認識合わせしておく
    - キックオフミーティングでは仕様の確認だけでなく、変更する箇所の危険性も洗い出しておくべき
- この場にPdM（Product Manager）とQAエンジニア（Quality Assurance）も同席すること
- エンジニアは必須

## ドキュメントに不備がないか確認すること

- Product Backlogや仕様書、Figmaがあるかどうかを確認する
    - ある場合はJIRAのエピックチケットにリンク付けすること
    - 開発をする上で常に確認できるようにするため

## 達成条件などは最初に確認すること

- 最低限下記は欲しい
    - やりたいこと（要求定義があればそちらで代替する）
    - ユースケース（こちらも同様）
    - 対応しない場合のリスク
    - 完了条件
    - 危険性
    - リリース目標
        - 着手開始
        - 開発期間
        - QA期間
        - リリース目標
        - リリース締め切り（ここがデッドライン）
    - 関連資料
    - 撤退条件

# プロジェクト進行中

## 前提条件が変わったらアサイン・スケジュール含め再検討する場を設けること

- 前提条件が変わった例
    - 担当者が急遽抜けてしまった
    - 事前に把握していなかった危険性が見つかった
    - 仕様が大きく変更した
- 担当者が変わった場合などは、難易度や危険性含めアサインされたメンバーが対応できるものか、サポートメンバーが必要なのかを検討すること
- PdMや関係者に前提条件が変わったことをエスカレーションすること
    - 危険性が新たに見つかった場合は振り返りなどでなぜ事前に見つからなかったのかを考えること

## アサインしたタスクの責任が取れなくなった人にはエビデンスを残してもらうこと

- 責任＝リリース後に保守作業ができる
    - 副業などを対象としている（また退職間近のメンバー）
- エビデンス＝事前に挙げた危険性の考慮や完了条件を満たしているものを項目として挙げ、それら項目が満たしたのかを残してもらう
    - フロントエンドの場合はスクリーンショット
    - バックエンドの場合はAPIレスポンスが望ましい
- ただし手作業だと手順を間違える可能性があるため、自動化が望ましい
    - クエリ叩くだけなどのインテグレーションテストの粒度まで落とす等の対応が理想
    - ゴールデンテスト：実行してその時の結果差分が想定通りかどうかを見る
        - メリット：テストを丸々実装する必要がない、デグレの心配がない、autifyよりも広い範囲をカバーできる、ランニング中の工数が減る
        - デメリット：ロールとかを対応しなきゃいけない、実装は多少必要なのでイニシャルコストはかかる
        - 参考： https://swet.dena.com/entry/2020/03/16/173000

https://swet.dena.com/entry/2020/03/16/173000

## スケジュールについて温度感の足並みを揃えること

- 足並みを揃えることでエスカレーションの判断が特定メンバーに依存しなくなる
- デッドラインはどこで、現在はどこまで進んでいるのかを常に認識しておくこと
    - 把握するためにStoryPointなどを振り分け全体の工数感を知ることは大切
    - タスクの細分化や不確定要素の高いものを優先的に潰すことで確実性を高める

# リリース前後

## リリースできそうな状態になったら改めてお触り会をすること

- 触っていくことでどんな機能を作ったのかを再確認する
- エンジニア以外の人にも触れてもらうことで違う視点の意見を取り入れる
- 事前準備はしっかりすること
    - 触れる環境
    - アクセス方法
    - 事前のデータ
- ここでリリース前に仕様が違う場合はリリースブロック要素として対応すること

## プロジェクトが完了したらお片付けすること

- プロダクトの仕様書がある場合はマージすること
- FigmaやNotion、必要であればGitHubも
- 振り返りの場を設け、ドキュメントを残すこと
    - 難航した場合は次のプロジェクトに活かすため
    - 順調に進んだ場合は型化をするため

## リリース後には利用率の経過を定期的にウォッチすること

- そのためにはログを仕込むことを忘れないこと
- 機能の利用率とプロダクト自体の利用率の変化をウォッチすることで、プロジェクト当初に考えていた顧客への影響度を測定することが可能
    - 影響度合いが大きい場合は今後のリファクタリングや追加実装を考慮に入れる判断材料になる

# 記事の最後に

1つ1つは当たり前のことですが、1つ1つを丁寧にやっていくことで良いプロダクト開発になっていくと思います。
PjMだけでなく開発メンバーも理解しておくことで円滑なプロジェクト開発ができるはずです。

また、HRBrainでは引き続き仲間を募集しておりますので最新の募集状況などは下記からご確認ください。

https://www.hrbrain.co.jp
読書感想文『テスト駆動開発』

# はじめに

2022年の8月に[『テスト駆動開発』(Kent Beck 著、和田卓人 訳)](https://shop.ohmsha.co.jp/shopdetail/000000004967/)を読んだので、内容の備忘録を残しておこうと思います。本の内容を全部書いていると、記事が明らかに長くなって、一目で辟易とする人が増えて読まれなくなってしまうと思います。軽いメモと思ってください。

原著は2002年に出版されているので、なんと20周年ですね！:clap_tone1:
名著なので皆さんは読んでいらっしゃると思いますが、この記事にお付き合いいただき、「そんな内容だったな」と思い出していただければ幸いです。

# テスト駆動開発(Test-Driven Devvelopment; TDD)の概要

**動作する**,**綺麗な**コードを作ることがテスト駆動開発の目的です。

## ルール

- 自動化されたテストが失敗したときのみ、新しいコードを書く
- 重複を除去する

## 手順

2つのルールに従って、レッド/グリーン/リファクタリングのサイクルでプログラムを育てていくことになります。
 
##### :red_circle:レッド：実装したい機能に対するテストコードを、いの一番に書きましょう。

まずはテストを書くんです。機能の実装の仕方を思いついた気になって、本体コードを書いてはいけません。:angry:
テストファーストが本体の実装をテストしやすい粒度にとどめるため、実装が独立性を保ちやすくなるからです。

##### :green_heart:グリーン：そのテストを通る本体コードを書きましょう。どんな手を使ってでも！！

先ほど書いたテストは、書いただけなのでもちろん通りません。どんな汚い手段を使ってでもテストを通らせましょう。:smiling_imp:
テストが通れば、コードを信頼するための軸が作られたことになります。そして、エンジニアは安心感で満たされて、コミュニケーションが増え、フィードバックをポジティブに捉えられるようになります。:relieved:

##### :tools:リファクタリング：テストを通す過程で生まれた重複を除去していく段階です。

なんとしてでもテストを通るように書いた本体コードは、普通のエンジニアなら到底受け入れられない醜いコードになっているはずです。例えば、以下のようなものですね。

```test.py
import unittest
import target

class TestSample(unittest.TestCase):
    def test1(self):
        self.assertEquals(3, target.sum(1, 2))
if __name__ == "__main__":
    unittest.main()
```
```target.py
def sum(first, second):
    return 3
```

他のテストを追加したら失敗するし、あたいはベタ書きだし、docstringはないし、、、
文句を言い出すとキリがないですが、テストは成功します。そして、test.pyとtarget.pyに重複が見られます！そうです、`3`です！！

コードをたくさん書いていかなくたって、重複が生まれてしまうものです。それを溜飲が下がるまでリファクタリングしていきましょう。
```target.py
def sum(augend, addend):
    """二つの引数の和を返す

    Args
        augend (int): 被加算数
        addend (int): 加数 
    
    Returns
        int: 二つの引数の和
    """
    return augend + addend
```

リファクタリングでコードを壊してしまいそうですか？大丈夫です。絶対的な信頼を寄せていいテストを持っているので、コードを書き換えるたびにテストを実行してもいいですし、不安を覚えてからテストを動かしてもいいです。すぐに一歩戻ることができます。:walking_tone1: 

今、グリーンの後にリファクタリングをしているので、リファクタリング最中に扱っている問題は一つなので、一歩戻るのも簡単です。

# 写経してみての雑感

TDDの概要や実践方法に触れました。TDDは自分のプログラミングをどうやって進めるかという話なので、チームメイトみんなで「いっせーのーせ」で始める必要がないから、試しやすいと思います。
『テスト駆動開発』の1章と2章には読みながらTDDの手順を追うことができるので、興味がある人は本を買ったり、図書館で借りたりして写経してみてください！

本書の写経で、僕がTDDを実感したことが以下の点です。
- リファクタリングで重複をまとめていく過程で、デザインパターンの活用が見えてきたり閃いたりする。まさにテストが開発や設計をドリブンしている、前進させる。
- テスト同士が絡み合っていると、たとえ一つだけレッドバーが現れたとしても、潜在的なエラーを疑いたくなってしまう。テストする機能を明確にしてから実装することが、本体コードにもテストコードにも独立性をもたらすので、その疑いが生じない。
- 「書いては消し」を繰り返すので、コードを消すことの躊躇いが薄くなる。自分が書いたコードは愛着が湧いて消しにくいけど、邪魔で醜いものは思い切って消さなきゃ！（本質は、テストがあるので、重要なコードの部分が分かるし、消しちゃってテストが通らなくなったなら、復活させればいいという話）

# テクニック

本書の3章は、TDDの方法やパターンを用意しています。その中のいくつかをメモ:pencil:します。

## TODOリスト

テストすべき事柄を忘れてしまわないように書き留めるリストを用意しましょう！
リストを作っておけば、実装中のセレンディピティを捕まえておく場所がはっきりしていて逃すこともないし、セレンディピティを追いかけてしまってやりかけを残すことも起きませんね。

## いつ作業を一段落させるか

独りでプログラミングをしているなら、次に戻ってきた時に前回の終了が分かりやすいように、最後のテストを失敗した状態で作業を一段落つけよう。
チームでプログラミングをしているなら、自分が書いてないコードにも自信を持たなくてはならないので、テストが全て通る段階で共有して一段落にしよう。

# おわりに

さて、簡単に『テスト駆動開発』の内容をおさらいしましたが、実際の本はまだまだ内容てんこ盛りです。また、訳者の方がテスト駆動開発の現在を解説してくださっています。
テストに関する議論が様々あるようですが、それらはまた余力が出てきた時にでもと思います。

本の中で次の言葉が書いています。

>TDDはテスト技法ではない。TDDは分析技法であり、設計技法であり、実際には開発のすべてのアクティビティを構造化する技法なのだ。

(『テスト駆動開発』第32章 p.278より抜粋)

TDDはXPのプラクティスの一つですが、開発者独りでも実践しやすいプログラミングプラクティスではあります。
しかし、テストを書いて満足するのではなく、テストを書くことでコードの構造を整える方に頭を使わなくてはいけませんね。

長文、駄文失礼しました。ここまでお読みいただきありがとうございました。
【Linux】特定の文字列以降を削除する方法

## はじめに

以下のファイルから「ここまで」という文字列までの内容を残しそれより後の文字列は削除する方法について記載します。  

```sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
ここまで
aaaaa
bbbbb
ccccc
ddddd
eeeee

```

## 削除方法

`sed`コマンドを使用して次のように実行することで特定の文字列より後の行を削除できます。  

```
sed -i "/文字列/q" ファイルパス
```

```terminal
$ sed -i "/ここまで/q" sample.txt 
$ cat sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
ここまで
```

なお「ここまで」も含めて削除する場合には以下のように実行します。  

```
sed -i '/文字列/,$d' ファイルパス
```

```terminal
$ sed -i '/ここまで/,$d' sample.txt
$ cat sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
```
ONNXの最適化ツールが便利

ONNXで推論を行うと

```py
import onnx
import onnxruntime

onnxfile = "models/hoge.onnx"
session = onnxruntime.InferenceSession(onnxfile)
```

以下のような警告が出る場合がある

```log
[W:onnxruntime:, graph.cc:3487 CleanUnusedInitializersAndNodeArgs] Removing initializer 'huga'. It is not used by any node and should be removed from the model.
```

使われなくなったイニシャライザが残ったままになってしまっているという警告なのだが、該当するイニシャライザをいちいち探して削除するのも面倒  
何か良い方法は無いのかとググったところ
[ONNX Optimizer](https://github.com/onnx/optimizer) というライブラリでONNXを最適化する方法が  
<https://github.com/microsoft/onnxruntime/issues/1899#issuecomment-840596510> にて紹介されていたので  
それを少し改変して使用

```py
from pathlib import Path

import onnx
import onnxoptimizer

onnxfile = Path("models/hoge.onnx")
onnx_model = onnx.load(onnxfile)
passes = ["eliminate_unused_initializer"]
optimized_model = onnxoptimizer.optimize(onnx_model, passes)
output_onnx_path = f"{onnxfile.parent}/{onnxfile.stem}_clean.onnx"
onnx.save(optimized_model, output_onnx_path)
```

不要なイニシャライザを削除したいだけなので今回は passes に `eliminate_unused_initializer` を指定したが、  
他にも任意の最適化オプションを以下から指定可能  
<https://github.com/onnx/optimizer/tree/master/onnxoptimizer/passes>  
どういう最適化を行うのかを詳しく知りたい場合は、ヘッダの中に説明が書かれているので、それを読むと良い

<https://github.com/PINTO0309/onnx2json> を使用して、最適化する前と後のJSONを比較してみると、  
不要なイニシャライザが削除されていることが確認できる

## 参考サイト

- [ONNXモデルのチューニングテクニック (基礎編)](https://cyberagent.ai/blog/tech/17300/)
- <https://github.com/microsoft/onnxruntime/issues/1899#issuecomment-840596510>
- <https://github.com/onnx/optimizer>
今更おすすめVSCode拡張機能集

# おすすめ拡張機能集

## Docker周り

### Remote-Containers
https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0

本記事を参照のこと。

### Docker
Dockerコンテナの構築、管理、デプロイをVSCodeのGUI上で行えるようにする拡張機能。

## Git周り
https://codelikes.com/vscode-git-plugin/

下記3点は同時に入れても干渉し合わないため、全て試してみる事をおすすめ。
筆者自身、全ての機能を導入済み。

### Git History
コミット履歴の確認・検索、そして便利なのが行単位での変更履歴の確認機能。
コミットした履歴のうち、この行どういった意図で変更したんだっけ？がすぐ分かるのがよい

### Git Graph
https://qiita.com/dbgso/items/4a2c6ab221eba00f19a9

コミット履歴を素敵に可視化してくれるツール。
個人的には後述のGitLensのCommitグラフの方が好み。

### GitLens
https://qiita.com/yoyoyo_pg/items/e7f010dd13f99e61beba

Commitグラフの可視化に加え、各種GitコマンドをGUI操作から行えるようにできる点が素晴らしい。
SourceTreeに慣れている人は、取っ付きやすいかもしれない。

ブランチ作りまくってプルだのマージだのしてると"git log --graph"でグラフ出したときにAAみたいになっちゃうので、いずれかのツリー可視化機能は入れておくと混乱しないと思う。

## コーディング

### Github Copilot (Nightly)
AIアシスタントサジェストツール(月額制)。
一回使ってみてほしい。精度が高すぎて気持ち悪いくらいのサジェストをしてくれる。
４０代おっさんREST API サーバーレスを学ぶ①

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## DB用意

DynamoDBを使います。
リージョンを東京にする。（Lambda関数を使う時リージョンが違うと問題が出る。）

![スクリーンショット 2022-11-29 191200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/b7b5d86a-59f5-8f74-a0e6-de92b22c7514.png)

テーブル名 users
パーティションキー id

それ以外はデフォルト

## IAM

ロールを作成するので左のロールをクリック
開いたら
左上にロールを作成があるのでそれをクリック

![IAMロール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/e3183c3d-f709-570c-ddd9-b5220df6414e.png)

Lambdaを選択（赤丸）

選んだら次へ

許可ポリシー選択
AWSLambdaBasicExecutionRole
AmazonDynamoDBFullAccess
を選択

終わったら次へ

ロールの詳細に行くので

ロール名を入力
今回はusers-role
下に行きロールを作成をクリック

## 参考

https://www.udemy.com/course/awsrest-api/
【Python】Macで作業環境（Safari、Chromeなどのアプリ＋α）のバージョンを一括出力する


記事を書く時、不具合を報告する時など環境としてコピペできるように出力してみました。
改善の余地は多々あるけど、とりあえず満足したのでメモがてら残します。

[subprocess](https://docs.python.org/3/library/subprocess.html)を使用します。


## 環境
MacOSバージョン: 12.6.1
python3バージョン: Python 3.9.13


## アプリのバージョンをPlistBuddyで取得する
Macにデフォルトで入っているplist編集コマンド`PlistBuddy`を使用します。

```sample.py
import subprocess

result = subprocess.run("/usr/libexec/PlistBuddy -c \"print :CFBundleShortVersionString\" /Applications/Safari.app/Contents/Info.plist", capture_output=True, shell=True, text=True)
print('safariバージョン: %s' % result.stdout) // safariバージョン: 16.1
```
`/Applications/xxx.app/Contents/Info.plist`からバージョン`CFBundleShortVersionString`を取得・出力してます。
上記がないアプリは対象外。キー名を変更するなど手を加える必要あり。


## `xx --version`コマンド実行で取得する
```sample.py
import subprocess

result = subprocess.run("python3 --version", capture_output=True, shell=True, text=True)
print('python3 バージョン: %s' % result.stdout) // python3 バージョン: Python 3.9.13
```

## 配列にアプリ名などを格納・ぶん回してまとめて出力する
### コード全体
```sample.py
import os
import platform
import subprocess
# import plistlib # ファイル操作ができるらしいが、今回は未使用

print("""## 環境
MacOSバージョン: %s
platform: %s""" % (
    platform.mac_ver()[0],
    platform.platform(),
))

# バージョンを取得するアプリなど格納した配列たち。
show_version_list = ["docker", "python3", "npm", "node", "swift"]
applications = ["XCode", "Safari", "Google\ Chrome", "Firefox"]

results = []

for item in show_version_list:
    result = subprocess.run("%s --version" % (item), capture_output=True, shell=True, text=True)
    results.append({ 'name': item, 'result': result.stdout.replace('\n', '') })

for app in applications:
    # PlistBuddyはMacにデフォルトで入っているplist編集コマンド
    path = "/usr/libexec/PlistBuddy -c \"print :CFBundleShortVersionString\" /Applications/%s.app/Contents/Info.plist" % app
    # 文字列で指定する場合、`shell=True`を付与する
    result = subprocess.run(path, capture_output=True, shell=True, text=True)
    results.append({ 'name': app.replace("\\", ""), 'result': result.stdout.replace('\n', '') })

for i, j in enumerate(results):
    print('{0}バージョン: {1}'.format(j['name'], j['result'])) # 改行なしで出力が分からなかったので、一旦空文字に置換してます

```

### 出力結果
```bash
## 環境
MacOSバージョン: 12.6.1
platform: macOS-12.6.1-arm64-arm-64bit
dockerバージョン: Docker version 20.10.17, build 100c701
python3バージョン: Python 3.9.13
npmバージョン: 6.14.17
nodeバージョン: v14.19.3
swiftバージョン: Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)Target: arm64-apple-macosx12.0
XCodeバージョン: 13.2.1
Safariバージョン: 16.1
Google Chromeバージョン: 107.0.5304.110
Firefoxバージョン: 106.0.5
```
【re:Invent2022】Lambda SnapStartの有効化方法(コンソール)

# はじめに
こん〇〇は！
re:Invent2022で発表された「Lambda Snap Start」ですが、さっそくどのように有効化したらよいか確認してみたので、記事にしました！
もうすでに、AWSのサイトに今回の記事の内容は書いてありますので、それを試してみた。といったような内容です。

# Lambda SnapStartとは
簡単に言うと、通常のcold startに比べ高速に起動できるサービスです。
Lambdaのライフサイクルは、init/Invoke/Shutdownの3ステップあります。
このうちinit部分を高速化するサービスです。
過去にLTをした時の資料があるので、こちらで説明します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/b2a3eaaa-5e2d-854b-dd26-d8da75f1355a.png)
通常init部分は数ミリ秒しかかからないものの、ランタイムやフレームワークの組み合わせによって10秒程度かかってしまう場合があります。
このinit部分で行われる実行環境の作成などを事前にして、SnapShotを取得/キャッシュしておきます。
Lambda関数が呼び出された場合に、実行環境などをイチから作るのではなく、SnapShotを呼び出してリストアすることで、init部分を高速化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/344fe5ea-e9bc-3879-1048-ab8d2ec6eda2.png)


# 前提条件
使用できるランタイムは「Java 11」のみ(2022/11/29現在)

# できないこと、できない環境/サービス
- プロビジョニングされた同時実行
-  arm64 アーキテクチャ
-  Lambda 拡張機能 API
-  Amazon Elastic File System (Amazon EFS)
-  512MBを超えるエフェメラル(一時)ストレージ

# 注意点
スナップショットは以下の場合削除されます。
- 関数または関数バージョンを削除したとき。
- 14日間の関数バージョンの呼び出しがないとき。(14日後に呼び出された場合再作成される。)

# 有効化方法
まず、Lambdaを作りましょう。
使用できるランタイムは「Java 11」のみなので、コンソール上からは「Java 11(Corretto)」を選択します。
また、アーキテクチャは「arm64」に対応していないため、「x86_64」を選択します。
あとはデフォルトでOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/99b7a272-1881-1fd4-a23a-bda14787667b.png)

作成出来たら、「設定」タブへ移動し、「一般設定」を見てみましょう。
画像の青線部分、現在はSnapStartが設定されていない状態(None)となっています。
有効化するために「編集」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/7f003075-f905-e1d4-9997-5006ba8c87fe.png)


青線部分の「エフェメラルストレージ」の容量は「512MB」を超えるものは対応していないため、「512MB」以下で設定してください。
赤線部分「SnapStart」がページ移動時は「None」となっていますので「PublishedVersions」に変更して、保存してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/c1014e0d-ee73-dcd5-b95c-145b745c8735.png)

一般設定画面に戻り、「SnapStart」の項目が「PublishedVersions」になっていれば設定終了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743619/03021da9-d91b-bebf-6282-7d0f9e3f7b33.png)

# 参考文献
https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html

https://docs.aws.amazon.com/lambda/latest/dg/snapstart-activate.html
C言語のprintfにはGoの%v相当のものが存在しない理由

Go言語のPrintf関数は `%d` や `%s` などのフォーマット指定を使って第二引数以降の値を埋め込んだ文字列を出力します。
また、 `%v` というどんな型に対してもいい感じに出力してくれる万能なフォーマット指定子もあります。
このPrintf関数はC言語のprintf関数が元になっていますが、元ネタのprintfには `%v` という便利なフォーマット指定子がなく、型の種類毎に別々のものを使う必要があります。
なぜ、C言語には `%v` 相当のものが存在しないのでしょうか？

# 答え
Goのinterface{}は元の型情報を保持しているが、C言語のva_listは元の型情報を保持していないため。

まず、GoのPrintfのシグネチャを確認します。
以下によると、`func Printf(format string, a ...any) (n int, err error)`というシグネチャであることが分かります。

https://pkg.go.dev/fmt#Printf

第二引数以降はany型という型で受け取っています。
このany型はinterface{}型と等価であるように定義されています。
そのため、Printf関数は第二引数以降で任意の型を受け取ることができます。

https://pkg.go.dev/builtin#any

Printf関数がaを受け取った直後ではinterface{}型ですが、文字列に変換するまでのどこかのタイミングでintやstringなどの具体的な型に変換する必要があります。
そのため、以下のようなコードで型switchを行っています。

```go
	switch f := arg.(type) {
	case bool:
		p.fmtBool(f, verb)
	case float32:
		p.fmtFloat(float64(f), 32, verb)
	case float64:
		p.fmtFloat(f, 64, verb)
    // 以下略
```

https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/fmt/print.go;l=707;drc=e79a4f71b7af648ef594f824951800ccc555d727

このような処理を行えるということは、Goではinterface{}型にアップキャストした後も元の型が何であったのかという情報を実行時まで保持していることが分かります。
そのため、%vというフォーマット指定子が渡されたとしても、元の型情報を使った適切なダウンキャストが実現できます。

一方でC言語の場合はどうでしょうか？
C言語のprintf関数は以下のシグネチャを持ちます。

```c
int printf(const char *format, ...);
```

https://en.cppreference.com/w/c/io/fprintf

第二引数以降の型情報が見つかりません。
`...` で受け取った引数は、 `va_*` というマクロを用いてアクセスします。

https://en.cppreference.com/w/c/language/variadic

va_listが...の情報を表しており、va_argが、 `...` から引数を順番に取り出すためのマクロです。
このマクロの第二引数に型を渡すことで、その型として値を取り出すことができます。

https://en.cppreference.com/w/c/variadic/va_arg

```c
va_list l;
va_args(l, int); /* int型として取り出す */
```

一見するとGoの型アサーションのような仕組みにも見えますが、元の型と異なる型として取り出そうとしたときの挙動が大きくことなります。
Goでinterface{}型をダウンキャストするときに、互換性の無い型にキャストする場合にはエラーが返されるかpanicが発生します。
一方でC言語ではそのような場合の動作は未定義です。多くの処理系ではでたらめなデータが返されることが多いです。
そのため、安全にダウンキャストできるかという確認が実行時にできず、Goのような型によるswitchも不可能です。

そのため、Goの%vのような任意の型に対して使えるフォーマット指定子はCのprintfには存在しません。
PythonでOpenImageIO(OIIO)を使ってOpenEXR画像に3DLUTを焼き込む

# 自己紹介
株式会社digitalbigmoのパイプラインエンジニアの小池@plinecomです。

# これは何？
OpenEXRに、3DLUTファイルを当てたくなる。それ、OpenImageIO(OIIO)でも出来るんです。OpenImageIOにOpenColorIO（OCIO)の機能が一部含まれているので、3DLutを適用した画像を作れる。そのやり方を示す。


# とりあえず、コード
```python:main.py
import OpenImageIO as oiio
import glob

if __name__ == '__main__':

    for path in glob.glob('/foo/bar/*.exr'):
        print(path)
        jpg_path = path.replace('.exr', '_lut.jpg')

        #Read File
        buf = oiio.ImageBuf(path)

        #Apply Lut File
        dst = oiio.ImageBuf()
        isOK = oiio.ImageBufAlgo.ociofiletransform(dst, buf,
                                                  "/foo/bar/test.cube",
                                                  False)
        if not isOK:
            print("ociofiletransform error: " + dst.geterror())
            continue

        #Write File
        dst.write(jpg_path)
```

# 必要なPython外部モジュール
* OpenImageIO
* NumPy

Dockerfileも用意した。
```Dockerfile:Dockerfile
FROM rockylinux:8
RUN dnf install -y which python3 epel-release
RUN dnf config-manager --set-enabled powertools
RUN dnf install -y python3-openimageio python3-numpy
```
```terminal:terminal
docker pull plinecom/py_oiio
```

# コードの説明

## Lutの適用の指示
```python:
        dst = oiio.ImageBuf()
        isOK = oiio.ImageBufAlgo.ociofiletransform(dst, buf,
                                                  "/foo/bar/test.cube",
                                                  False)
```
dstな仮バッファを用意して、そちらにtest.cubeのLutファイルを適用している。最後のFalseは逆変換であることを示す。

```python:
        if not isOK:
            print("ociofiletransform error: " + dst.geterror())
            continue
```
エラーハンドリング。このociofiletransform()関数は受け入れてくれるLutファイルの形式の制限が厳しいので、なんで通らなかったのかエラーハンドリングして、エラー内容を出力させる。こうすることで、何が問題なのか解決の手がかりとなる。

# 宣伝
株式会社digitalbigmoでは美肌プラグインの販売や映像VFXの制作業務を行なっています。ご興味のある方は、webページを見にきてください。一緒にお仕事しましょう。

https://digitalbigmo.com

# 参考文献
[OpenImageIO本家（英語）](https://sites.google.com/site/openimageio/home)
[OpenImageIO本家リファレンス（英語）](https://openimageio.readthedocs.io/en/latest/imagebufalgo.html#color-space-conversion)
Figmaについての初歩的な知識

# ジャンル
Web/UI/UXデザイン、プロトタイプ作成

# プラットホーム

1. ウエブ版
2. デスクトップ版
    - Windows 32-bit, 64-bit
    - Mac
    - Linux
3. モバイル版
    - Android
    - iOS

<a href="https://www.figma.com/ja/downloads/"><img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/f45d7dbb-532c-26a8-1790-0811c90ffe6c.png"/></a>

# 料金

1. スターター　（無料）
    - ３つのFigmaファイルと３つのFigJamファイル
    - 個人用ファイル数無制限
    - コラボレーター数無制限
    - プラグイン、ウィジェット、テンプレート
    - モバイルアプリ
2. プロフェッショナル　（2,250円／月）
    - Figmaファイル無制限
    - バージョン履歴数無制限
    - 権限の共有
    - 共有プロジェクトとプライベートプロジェクト
    - チームライブラリ
    - 音声での会話
3. ビジネス　（6,275円／月）
    - プロフェッショナルのすべての機能
    - 組織全体のライブラリ
    - デザインシステムアナリティックス
    - ブランチ機能とマージ機能
    - 管理・請求の一元化
    - プライベートのプラグインとウィジェット
    - シングルサインオン
4. エンタープライズ　（Figma 10,458円／月、FigJam　697円／月）
5. Education Plan （無料）
    - プロフェッショナルのすべての機能

# 構成

無料版では、1つのチームに1プロジェクトで、プロジェクトの中には3ファイル、ファイルの中には3ページという制限があります。
![g2428.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/0c7bd211-284e-53a3-4c7b-7eae75ea6755.png)
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/693d3671-c678-4047-eaba-321b3ab8c96c.png)

# 操作性
豊富な機能があり、高度なデザインが直感的に作成できますが、操作を覚えるには、一通りのトレーニングが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/7c8aa799-0638-bf2b-18fc-7176d56b7850.png)

# Power Apps　キャンバスアプリの作成
Figmaで作成されたページを、Power Apssのアプリとして読み込むことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/0629f390-3a96-3cd4-98f2-4ea3584e7022.png)

https://youtu.be/XH0XmwpqVuQ

# FigmaJam
FigmaJamは、オンライン・ホワイトボードです。Figmaのデザインに関してのブレインストーミングに使えますし、そのたのミーティング、コラボレーションで使用することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/4fc32441-8edf-c50b-5b53-1ff9021a7ec0.png)

https://youtu.be/FxdoM1B7Wo8

https://help.figma.com/hc/en-us/articles/1500004362321-Guide-to-FigJam
Bizrobo!_コンバータのif Then

### はじめに
変数判定ステップのオペレータが「次を含む」「次を含めない」「次で始まる」「次で終わる」を使用し、
その結果で変数に値を格納する処理があったとします。

その際にトライステップと変数判定ステップを利用して処理していたものが、
コンバータのみで同じような処理ができるので、そちらの方法を紹介します。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/638370e5-755e-d8b4-b368-e88c8bea79ab.png)


### 処理概要
ファイル名に「売上」という文字が含まれていれば、結果という変数に「処理する」を設定。
ファイル名に「売上」という文字が含まれていなければ、結果という変数に「処理しない」を設定。
を設定するロボットを作成します。

　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/7457aa58-b4af-84af-2e18-63001228ab72.png)

トライステップから右側が変数判定ステップで変数を判定して、ロボットを作成したもの。
ブランチ下側がコンバータのみで処理になります。


### 設定
・トライステップの場合
　変数判定ステップのアクションタブ
　ファイル名に「売上」が含まれているか判断
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/2206ead7-7106-0ed9-c2da-2082dfe4c52a.png)
　変数判定ステップのエラー処理タブ
　ファイル名に「売上」を含んでいる場合は次の代替手段を試行
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/6df6ba43-73e4-5f42-e99a-b7cbfb8c0a2f.png)
　変数の割当ステップの右側のAssign 結果
　ファイル名に「売上」が含まれているため、変数の結果に「処理する」を設定
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/03f20caf-7f6f-e700-0eec-e4e8a4ef3397.png)
　トライステップ下側のブランチのAssign 結果
　ファイル名に「売上」が含まれていないため、変数の結果に「処理しない」を設定
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/d64d4bfd-be74-fd0f-55b8-265c24d58b5c.png)

・コンバータのみの場合
　変数割当ステップにコンバータを設定
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/530ae58b-8d05-1481-69df-cd017364a7f6.png)
　コンバータの1つ目でファイル名を取得(if Thenでテスト入力値として参照される)
　コンバータの2つ目でif Thenを設定
　if Thenはその他＞if Thenになります。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/7bccc4e6-a6ff-7cfd-91e9-3dd0ccafcd4e.png)
　if Thenの画面(テスト入力値にコンバータの1つ目で取得したファイル名が表示されています)
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/2e54ecab-c0cc-a78b-5e53-c35433618863.png)
　「+」ボタンから条件(if)を設定します
　今回は「次を含む場合」を選択しています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/dfc6d7a9-04c0-f9b4-e32f-374d226723fe.png)
　テスト入力値に含まれる文字を「次を含む場合」へ、テキスト値は条件を満たした場合に返す値を設定します。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/36362ab7-fbae-8c59-48e5-ceb4ba334940.png)
　テスト入力値に「売上」が含まれている場合は結果という変数に「処理する」を設定したいため
　次を含む場合に「売上」、テキスト値に「処理する」を設定
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/5778eba3-f19c-11e8-d26a-e77a4f41bbb3.png)
　「他の」は設定した条件以外(eles)の場合の処理になります。
　テスト入力値に「売上」が含まれていない場合は結果という変数に「処理しない」を設定したいため
　テキスト値に「処理しない」を設定
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/c153963c-27d4-d1df-82bb-ace1922e1ed6.png)
　試しにテスト入力値から「売上」を削除するとテスト出力が「処理しない」になりました。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/9c140252-269b-8eaf-286d-7bd58ffd337f.png)

### まとめ
ざっとした紹介になったため、分かりずらい点があったかと思います。
普段、よく利用するコンバータは限られたものになっていて、
他にどんなコンバータがあるのかなと思い、触ってみました。
そんなこともできるんだということが伝われば幸いです。
BizRobo!_日付間の時間を取得について

### はじめに
コンバータ内にある日付間の時間を取得という機能について、最近学んだことをまとめたいと思います。
日付間の時間を取得とは設定した2つの日付から時間や日数を取得する機能です。

### 実際に使ってみた

比較日付という変数に日時(2022-10-10 4:00:00)を設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/bef7ae2d-9c53-e131-5f0d-115b1a4a54a7.png)

コンバータの1つ目で現在の日時(2022-10-17 14:51:50)を取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/5e28fc9f-700b-1c88-a18d-0476ab10bad0.png)

日付間の時間を取得の画面
別の日付(2022-10-10 4:00:00)となり、
テスト入力値はコンバータの1つ前の処理結果(2022-10-17 14:51:50)の差がテスト出力欄に表示されます。
2022-10-10から2022-10-17は7日後のため「7」となっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/b70eba9b-8287-7e32-ad2c-3ac3cf7173a2.png)

試しに別の日付を現在の日時に変更すると...

比較日付は先ほどと同じく(2022-10-10 4:00:00)を設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/bef7ae2d-9c53-e131-5f0d-115b1a4a54a7.png)

コンバータの1つ目で比較日付(2022-10-10 4:00:00)を取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/c67a0815-c6c1-a74e-e71f-aa41511a3174.png)

日付間の時間を取得の画面
別の日付(2022-10-17 14:51:50)となり、
テスト入力値はコンバータの1つ前の処理結果(2022-10-10 4:00:00)の差がテスト出力欄に表示されます。
2022-10-17から2022-10-10は7日前のため「-7」となっている。
日付間の時間を取得の画面の「符号付きの差を取得」のチェックを外すと「7」がテスト出力欄に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2127851/218a0407-0fd4-d23c-bf3a-c7981b96f13a.png)


### まとめ
日付間の時間を取得の機能は、テスト入力値から別の日付までの差を求める。
「符号付きの差を取得」のチェック有りだとテスト入力値が別の日付を過ぎているとマイナス表記で出力される。
エクセル小技

# エクセルのちょっとしためんどくさい・困ったを解決する小技集

## データ入力・削除など

###  フィルタで抽出したデータだけを残す／削除する
http://sasayakanaon.blog.fc2.com/blog-entry-9.html

Alt+;

### 連続データの作成
選択セル枠の右下をドラッグ・・・は当然習得しているとして、Shiftキーを押しながらWクリックという技もオススメ。
いい感じの位置(次の空白セル位置など)まで連続データを入力してくれる。

## PowerQuery関係

### グループ化に対するカテゴリ変数の列挙
https://answers.microsoft.com/ja-jp/msoffice/forum/all/powerquery/f7e62416-8dc9-47df-8d54-21d07d54b6e3

グループ化して数値の集計、というのはよく使う機能だが、カテゴリ変数のリストアップってGUIの標準機能になさそうなので、上記で対応。
主キーに対してユニークなA,B,Cというカテゴリ変数があったとき、A/B/Cと記載したいならば本処理を行う。

## ショートカットキー色々

### シートの切り替え
**Ctrl + PageUp/Ctrl + PageDown**
ほんとによく使う。WindowsだとFn+上下キーがPageUp/Downだったりするので、合わせて使おう。

### 色々
**Alt+色々**
Excelでは、Altキーを押すと各種タブに対するショートカットをサジェストしてくれる機能が備わっている。
初めて使う機能についてはクリック操作の方が早かったりもするものの、よく使うものは手に馴染ませると早く操作できる。
そんななんでもかんでも覚えられませんわ、って人に助かる機能だったりする。

### 範囲のテーブル化
**Ctrl+T**
テーブル化って意外と手数多いので、おすすめショートカットのひとつ。
CloudFormationスタック作成時の設定について

# CloudFormationスタック作成時の設定について
### 1 スタック作成 
AWS CloudFormation管理コンソールから、スタックの作成をクリックし、[新しいリソースを使用(標準)]を選択して下さい。

### ２ テンプレート選択 
[スタックの作成]で、[テンプレートの準備完了]を選択し、[テンプレートファイルのアップロード]>
[ファイルの選択]で、テンプレートを選択します。

### ３ パラメーター値入力 
各パラメータを入力します。`スタックの名前は任意の名前を入れて下さい`
![スクリーンショット 2022-11-22 20.50.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/12282fcd-5e51-a948-9f79-2232e1a85565.png)

### 4 スタックタグ入力 
スタックにタグを付与したい場合は入力下さい
![スクリーンショット 2022-11-22 20.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/1ba78b6d-bf29-c31f-8c2e-6e25c011e770.png)

### 5 アクセス許可
スタック実行時に必要なロールを自動で付与したい場合は空欄にして下さい。
![スクリーンショット 2022-11-22 21.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/ff19f316-4f8c-dcfe-3511-883572fcd868.png)

### 6 スタックの失敗オプション 
スタックが失敗した場合に、正常に作成さえれたリソースを保持するか削除するかどうか
![スクリーンショット 2022-11-22 21.35.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/1dbed758-5556-baa0-b645-eb8dd554b909.png)

### 7 スタックポリシー 
スタックの更新を制限したい場合は追加して下さい。
![スクリーンショット 2022-11-22 21.40.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/6fa80130-3090-7161-5bba-508016fa7eb4.png)

### 8 ロールバック設定
スタックの作成および更新時にCloudWatchアラームを設定して、スタック作成,更新後に特定の時間以内にアラームが発生した場合ロールバックする。
![スクリーンショット 2022-11-22 21.53.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/85b74928-9339-48c1-7b52-b9b4d12d5cde.png)

### 9 SNS通知 
スタックの作成、更新時にSNS通知が必要な場合は設定して下さい。
![スクリーンショット 2022-11-22 21.55.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/58038c65-4695-994a-55b8-7efd6d77e491.png)

### 10 スタックの作成オプション
スタックの作成時間に制限が必要な場合は設定して下さい。
![スクリーンショット 2022-11-22 21.56.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/7d6803d6-50c6-faf8-6680-7916f531a7e3.png)

### 11 確認 
上記の設定が終了しら`次へ`を選択して下さい。
![スクリーンショット 2022-11-22 22.01.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/f4960a72-75d5-f582-e799-a85c282b658c.png)

### 12 最終確認 
終了したら送信を選択して下さい。
![スクリーンショット 2022-11-22 22.02.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/bd027601-80c8-070a-08c3-f1ee4ec91083.png)

### 13 スタック正常終了確認 
ステータスが`CREATE_COMPLETE`になったらスタックが正常終了しました。
![スクリーンショット 2022-11-22 22.04.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983197/81d20c09-e5bb-db59-0654-24c78ab1a73d.png)
SVNメモ

開発現場にて使用している「SVN」について簡潔にまとめていきます。

# そもそもSVNって何？
正式名称は、**「Apache Subversion（アパッチ・サブバージョン）」**。
オープンソースのバージョン管理システムであり、誰でも無償で利用することができます。特に複数人で行うソフトウェア開発においてはソースコードやドキュメントの管理目的で重宝され、データの復旧や変更内容の履歴チェックが可能です。

# SVNとGitの違いは？

一言で言うと、SVNは **「集中型バージョン管理システム」** 、Gitは **「分散型バージョン管理システム」** に大別されます。
**集中型バージョン管理システム**・・・サーバにある「リモートリポジトリ」でソースコードのバージョンを管理しています。開発者はリモートリポジトリにアクセスして自身のローカルPCに指定したバージョンのソースコードをチェックアウト（ダウンロード）して開発します。また、修正や追加したソースコードはリモートリポジトリへコミット（登録）します。

**分散型バージョン管理システム**・・・開発者自身のローカルPCに「ローカルリポジトリ」を持ちます。開発者はこのローカルリポジトリに修正や追加したソースコードをコミットし、リモートリポジトリにプッシュ（反映）することでローカルリポジトリとリモートリポジトリの内容を同じに合わせます。

# 基本用語一覧
### リポジトリ（repository）
Subversionの核となる部分。ファイルや更新履歴、変更内容などを集中的に格納する場所（書庫のようなイメージ！）。

### チェックアウト（checkout）
リポジトリから初めてファイルを取り出しローカルに保存すること。

### 作業コピー（working copy）
チェックアウトで作成されるリポジトリのコピーのこと。

### .svnフォルダ
作業コピーを管理するのに .svn というフォルダを使用する。
※隠しフォルダとなっている点は要注意！

### コミット（commit）
ローカルコンピュータ上の作業用コピーに加えた変更をサーバのリポジトリに反映すること。

### リビジョン（revision）
リポジトリがコミットを受け付けるたびに発行される番号のこと（別名：バージョン番号）。

### ブランチ（branch）
開発ラインを分岐(履歴の流れを分岐)して記録していくためのもの。分岐したブランチは他のブランチの影響は受けないため、複数の開発ラインを並行して進めていくことを可能に。

### タグ（tag）
ある時点のプロジェクトの「スナップショット」に該当するもの。

### リバート（revert）
作業用コピー上で行われた変更を元に戻すこと。

### コンフリクト（conflict）
同時に同じファイルに修正等を行い、作業が衝突すること。

### 更新（update）
リポジトリ上から変更のあったものを再ダウンロードすること。更新を行うと、ユーザがリポジトリに対して加えた変更と作業用コピーが同期されます。

# 参考
公式サイト：https://subversion.apache.org/
vagrant plugin install で SSL verification errorが起きたときの対処

#### エラーとなった原因
UTMが導入されている環境でSSLインスペクションを行っているため、CA証明書がUTMによって書き換えれてしまっていたため発生していた

#### 対処
「C:\Hashicorp\Vagrant\embedded\cacert.pem」にUTMが使用している信頼すべきCA証明書をBASE64形式で追記することで回避

#### 手順
- CA証明書を開く
- 詳細タブで「ファイルのコピー」
- 出力形式「Base64 encoded X.509」でファイルに出力する
- 出力されたファイルをテキストエディタで開いて内容を「C:\Hashicorp\Vagrant\embedded\cacert.pem」に追記する
UnityのAndroidリリースビルドだけ起こったバグの話

## 環境
Unity Editor: Unity 2021.1.6f1
Platform: Android
OS: macOS Monterey(12.6)
Target API Level: Android 11 (API Level 30)（当初）
## リリースビルドだけ起こるバグ

UnityのAndroid版ゲームのビルドを作っているとき、Debugでは問題ないのだが、Releaseでビルドしたら進行不能バグに遭遇した。
logcatで内容を見てみると、いろんなことで以下の例外が出ている。

```
E/Unity: AndroidJavaException: java.lang.ClassNotFoundException:
```


「ClassNotFoundException」つまり、そのクラスが見つからないということ。しかし該当のファイルは存在するし、そもそもDebugでは問題なく動いている。

## 問題の洗い出し

どういうことかと調べたら、どうやら「ProGuard」という難読化ツールが名前を変更したから、らしい。
しかしそもそも「ProGuard」なんてツールを使用した覚えはないなのだが、、、

よく調べていくと、どうやら「Minify」というツールがAndroidのReleaseビルドで発動するようにデフォルトでなっているようで。

ProjectSettings→Player→Publish Settings→Minify
![スクリーンショット 2022-11-29 17.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/face0657-b54f-bb7e-1fdd-ac97a837010f.png)
それのおかげ（それのせい？）で「ProGuard」が発動し、例外を吐いていたということのようだ。

つまりまとめると、

```
Release ビルドにする
　↓
MinifyはReleaseビルドではデフォルトオンになっているのでMinify発動
　↓
MinifyのなかでProGuardがコードの難読化が発動
　↓
自分のソースコードは難読化が成功するのだが、外部プラグインの難読化が整合性が取れなくなる
　↓
プラグインの「ClassNotFoundException:」例外が出る
```


という仕組みだったようだ。

## 難読化してほしくないプラグインの設定

Assets/Plugins/Android/proguard-user.txt

というテキストファイルを作って、これにProGuardで難読化してほしくない部分を追記していく。

どう書けばいいかわからないと思うが、だいたいそのプラグインの「ProGuard項目」にどう書けばいいか書いてある。

例えば、「applovin SDK proguard」とかで検索すると、それらしい項目があるので、

```
-keepattributes Signature,InnerClasses,Exceptions,Annotation
-keep public class com.applovin.sdk.AppLovinSdk{ *; }
-keep public class com.applovin.sdk.AppLovin* { public protected *; }
-keep public class com.applovin.nativeAds.AppLovin* { public protected *; }
-keep public class com.applovin.adview.* { public protected *; }
-keep public class com.applovin.mediation.* { public protected *; }
-keep public class com.applovin.mediation.ads.* { public protected *; }
-keep public class com.applovin.impl.*.AppLovin { public protected *; }
-keep public class com.applovin.impl.**.*Impl { public protected *; }
-keepclassmembers class com.applovin.sdk.AppLovinSdkSettings { private java.util.Map localSettings; }
-keep class com.applovin.mediation.adapters.** { *; }
-keep class com.applovin.mediation.adapter.**{ *; }
```
引用：https://developers.is.com/ironsource-mobile/unity/applovin-mediation-guide/#step-3

それを丸ごとコピーして、proguard-user.txtに追記していく。

その作業を**全て**の外部プラグインに関して行うということになる。もし忘れてしまうと、実行時にひっそり例外が出るだけでビルドできてしまうので、細心の注意が必要となる。

## Androidビルドの険しい道は続く

ちなみにこの後もまだ「Gradle地獄」が続くのだが、その話は次回→[「UnityのAndroidビルドでAPIレベル31にしたらGradle地獄だった話」](https://qiita.com/warapuri/items/17721b113be8c44e5369)
Amazon EFS Elastic Throughput モードがリリースされたので調査・検証してみた。(2022年アップデート)


2022/11/27　Amazon EFS Elastic Throughputモードが利用可能になりました。
[Amazon EFS Elastic Thtoughput](https://aws.amazon.com/jp/blogs/aws/new-announcing-amazon-efs-elastic-throughput/)


## どんなモード?
・**Elastic Throughput モード**はワークロードに合わせて自動でスループット性能を調整
・データの読み取り量、書き込み量に対して料金を支払う

これにより、スループットパフォーマンスの予測が難しく、急変する可能性のあるワークロードに最適な手段です。

## 従来のEFSについて

従来のEFSには2種類のスループットモードがありました。
1.ファイルサイズとバーストクレジットでパフォーマンスを調節する**バーストスループット**
2.事前に設定し、高レベルなスループットを確保する**プロビジョニングスループット**

しかし、**バーストスループット**には、
バーストクレジットの上限を使い切るとパーフォーマンスが極端に低下する
**プロビジョニングスループット**には、
ピークに合わせてプロヴィジョニングをするとお金がかかりすぎる
という懸念点がありました。

今回リリースされた**Elastic Throughput モード**を用いることで、自動でスループット性能を調整し、さらに料金も、データの読み書き量に対しての支払いのため、これらの問題は解決します。

## どうやって使うの？

ファイルシステムの作成→カスタム→パフォーマンス設定で、
以下の項目を選択することで使用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2988434/851842a3-aa9e-cbbe-ecd4-ac03ac24e1ce.png)

さらに、既存のEFSに対しても、全般→編集→パフォーマンス設定により
**Elastic throughputモード**に変更できます。

## まとめ

**Amazon EFS Elastic Throughputモード**がリリースされたのでその機能や使い方をまとめてみました。

次の記事では、実際に他のモードとの比較検証を行いたいと思います。

## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [New – Announcing Amazon EFS Elastic Throughput](https://aws.amazon.com/jp/blogs/aws/new-announcing-amazon-efs-elastic-throughput/)
InterlockedAddをfloatで扱えるようにする


昔，MLS MPM Fluidの最適化をしていた時に（パーティクルの数を増やすだけの目的），一部, float型の値をスレッドセーフに加算する必要があったのですが，提供されている関数（InterlockedAdd）がintにしか対応していなくて，困っていたため, [edoさんの記事](https://qiita.com/edo_m18/items/4b23846b8a97ec2a21de)も参考にしながら，実装しました．

**HLSLのfrac関数や，どの数値で割るかによって誤差が発生する**ので，[簡易的なテスト](https://github.com/supertask/ComputeShaderTips/blob/main/Assets/FloatToInt2/FloatToInt2.cs#L175-L198)もしています．

実際のコードは以下のような感じです．

```
//
//
//
// example:
//     v = 10.25609895412
//     (int)10.25609890412 * 10000 -> 102560.989541 -> 102560
//     (int)0.989041 * 10000 -> 9895.41 -> 9895
//
//     102560 / 10000 -> 10.256
//     9895 / 100000000 -> 0.00009895
//     10.256 + 0.00009895 -> 10.25609895
//     
// BTW max value of int: 2147483647
//
//#define F2I_DIGIT 256
//#define F2I_DIGIT 512
#define F2I_DIGIT 1024 //Must be 2 ^ x
#define F2I_DIGIT_2SQRT F2I_DIGIT * F2I_DIGIT 

int2 ConvertFloatToInt2(float v)
{
	float f1 = v * F2I_DIGIT;
    int i1 = (int)f1;
	float f2 = (f1 - i1) * F2I_DIGIT; 
	//float f2 = frac(f1) * F2I_DIGIT;  //This does not work correctly!!
    int i2 = (int)f2;
	return int2( i1, i2 );
}

float ConvertInt2ToFloat(int2 v)
{
	float f1 = ((float)v.x) / F2I_DIGIT;
	float f2 = ((float)v.y) / (F2I_DIGIT * F2I_DIGIT);
	return f1 + f2;
}
```