OmniAICreator/Qiita-1.07M huggingface dataset:
Rustの関数テーブル呼び出しは速いのか？

# 以前このような記事を書きました
https://qiita.com/segfo/items/4a17702cd2825be1e1bd

# パフォーマンスの側面だとどうだろう？
もしきれいに書いてもパフォーマンスが出なければ、使えない書き方だなーと思ったりしました。
けど、matchやifをダラダラ書くのも嫌だなー
どこかで妥協点ないかなー・・・
っていうのが動機です。
要はバランスです。
なので、簡易的に計測してみました。

1実行あたり　50000x26文字　ぶん回す。
それをさらに11回程度外部から呼び出すのを繰り返す。

そうした時にどの程度の差があるのか？というざっくり計測をしました。

ソースコードは以下のPlaygroundにあります。

オリジナル（記事で書いた物）

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=990cdcdb55fd6b67d7ca15cecc94c3ca

条件分岐のみ

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9be9916d39578ff83daaca7d10af4fd6

オリジナル+一部分岐（改良）

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d76ad6007dbe576436fee0bd7d695677

# 試験条件
CPU：AMD Ryzen7 1800X Eight-Core Processor
MEM：64GB
OS：Windows 10 21H2

ビルドコマンドとCargo.tomlのビルドオプションは以下のとおりです

```
cargo build --release
```
``` Cargo.toml
[package]
name = "cond_array"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[profile.release]
opt-level = 3
overflow-checks = false
debug = false
debug-assertions=false
lto=true
panic="abort"
incremental=false
codegen-units=1
rpath=false
```


# 結果
条件分岐でゴリ押ししたものが意外と速くて「おやおや？」と思いました。
そして改良版の実装をしてみたところほぼ条件分岐版と変わらないパフォーマンスになりました。
また、オリジナルの実装が一番低速である　ということがわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/15552796-9b2e-f9c5-1414-a5976161857c.png)

# どうしてこうなったのか
配列でアクセスしたらパイプラインハザードとか起こりづらくてめっちゃ早くなるんじゃね？って思っていたので
原因を簡易的に見てみたところ、以下のことがわかりました。
- 条件分岐版は最適化時に関数を並び替えます。
- 関数テーブル版（オリジナル）は並べ替えが起きません。（起きづらいです）
- 関数テーブル版（改良版）は条件分岐部がいい感じに最適化されます
 
また、以下は考察です。
関数コールそのものが分岐命令だったことを完全に失念していました。（なのでどちらにせよって感じですし、今のCPUは分岐命令最適化機能が入っているのでそんなに気にすることではない）
単に分岐するのであれば、最速1回で済むところを、関数呼び出しの場合はcall-retで確実に2回分岐することになります。
なので遅くなっているのかな？

という感じでした。
過ぎたるは及ばざるが如しってやつですね～
見通しいいじゃん！って思ってやり過ぎると見通しが悪くなったりパフォーマンスが落ちるよ！
というお話でございました。

# 教訓っぽいもの
if/matchも関数テーブルも嫌いすぎず、読みやすさが上がる方法で書けばよい。
A/Bテスト（RCT）におけるノンコンプライアンスと操作変数法の応用 をRで実装してみた。

## はじめに
A/Bテスト（RCT）におけるノンコンプライアンスと操作変数法の応用
https://qiita.com/s1ok69oo/items/d9f3a3860388f3b9911d
が面白そうだったのでRで実装してみました。

数式等の詳細は元記事が丁寧に書いてあるのでご参考ください。
(私だと理解が怪しくて解説できる気もしない)
内容に誤り等ございましたらご指摘いただけますと幸いです。

## 問題の状況
CRMのメールマーケティングを考えます。新商品の発売を、会員へのメールで宣伝するとします。
ランダムにメールの送付対象を選定し、その効果を見るにはどうすればよいでしょうか。

考えなければならない事項
・メールを送付する対象はランダムに選定したが、そのあと開封するかは会員次第
・開封する会員はそもそも購入意欲(未観測)が高いと推定される、つまりメールの効果が過大推定される懸念

メール配信：Z
メール開封：D
購入の有無：Y
購入意欲　：U (未観測の値) 
のようにそれぞれ変数を設定したとき、そのDAGは以下の通り

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1951021/e79d40c4-72bb-7685-837d-06ef7edd9e1e.png)

:::note warn
メールの効果は開封後を前提で考えており、未開封状態でのメール効果はないという仮定で試算を行なっています。例えば、タイトルだけ見て購入意欲が向上することはない or かなり小さいので無視できるという発想です。
:::

## Rを用いたシミュレーション

~~~
rm(list =ls())
library(dplyr)

# データの設定
set.seed(99)
size = 5000
# ----------------------------- 
# 各カラムを乱数で生成
# -----------------------------
# 潜在的な購入意欲(実際は観測不可)
U = runif(n = size,min = -5,max = 1)

sigmoid = function(X){1/(1+exp(-X))} # シグモイド関数を定義する
d_prob = sigmoid(U) # 0～1の範囲にスケーリング

# メール配信の有無
Z = rbinom(size, 1, 0.5)# ※sample関数でいい
# sample関数を使う場合
# Z = sample(2,size = size,replace = TRUE,prob = c(0.5,0.5))-1

# メールの開封
D_i = rbinom(size, 1, d_prob) #i番目の人の購入意欲を元に開封フラグ
D   = Z * D_i #データに矛盾が出ないよう配信=0の場合は0にする

# 購入実績
y_prob = (U+5)/24 + 0.3*D #Dはダミー変数。開封した場合は0.3が足される設定
Y = rbinom(size, 1, y_prob)
# ----------------------------- 
# dfの生成
# -----------------------------
df <- data.frame('メール配信の有無'= Z
                 , 'メールの開封'= D
                 , '購入の有無'= Y)
df

# ----------------------------- 
# 試算：メール見たときの効果ってどうだったの？
# -----------------------------
# フィルター
df_z1 = df %>% filter(メール配信の有無==1)%>% select(購入の有無)
df_z0 = df %>% filter(メール配信の有無==0)%>% select(購入の有無)
df_z1_d1 = df %>% filter(メールの開封==1)%>% select(購入の有無)
df_z1_d0 = df %>% filter(メールの開封==0)%>% select(購入の有無)

# パターン1.メール配信ありの場合の購入率 - メール配信なしの場合の購入率
df_z1 %>% sum() /df_z1 %>% count() -
df_z0 %>% sum() /df_z0 %>% count() 

# パターン2.メール配信同士で開封の場合の購入率 - 開封なしの場合の購入率
df_z1_d1 %>% sum() / df_z1_d1 %>% count() -
df_z1_d0 %>% sum() /df_z1_d0 %>% count() 

# パターン3.開封の場合の購入率 - メール配信なしの場合の購入率
df_z1_d1 %>% sum() /df_z1_d1 %>% count() -
df_z0 %>% sum() /df_z0 %>% count() 

# パターン4.(配信がある場合の購入率- 配信がない場合の購入率) / (配信されたうちの開封率)
(df_z1 %>% sum() /df_z1 %>% count() -df_z0 %>% sum() /df_z0 %>% count())/
(df_z1_d1 %>% count() /df_z1 %>% count()) 
~~~

## 出力結果の比較
・パターン1.　0.06622　過少
・パターン2.　0.38122　過大
・パターン3.　0.37317　過大
・パターン4.　0.30566　適切

## 操作変数法に関して
上記の推計が成立するのは、操作変数が成立する場合のみです。
操作変数とは効果量を知りたい処置変数Xにのみ影響を与え、結果Yには影響を与えない変数Zのことです。
 
操作変数が成立する前提条件は3つあります。
1：操作変数の外生性：Zと未観測の共変量Uの相関0
2：操作変数の関連性：Zと処置変数Xの相関あり
3：除外制約：Xを行なった時のYへの影響はZに影響されない
 
今回の事例を考えると、以下の通り上述の条件を満たすことが分かります。
1.本来未観測の共変量Uは多く存在し、Uに関する相関は観測不可のため検証の余地はない。
　今回想定のU(購入意欲)に関してのみ考えると、ランダム選定のためZ(メール送付)とは独立。
2.配信と開封には相関がある
3.開封していない場合、Z(配信)のY(購入)への影響は0と考えられる

## ザックリ結論
DAGを考えたときに今回のように操作変数が設定可能な形になっていた場合は
操作変数法の導入を検討し、パターン4の形で求めると適切に効果が求められる

## 終わりに
twitter: https://twitter.com/nekobo_01 にて統計やデータサイエンスに関するツイートをしてます。
よければフォローください。
[IDMC]Sourceをパラメータ化して実行時に動的指定する

## はじめに
Informatica Intelligent Data Management Cloud(IDMC/旧称IICS)でのちょっとしたTipsを纏めていきます。日々の活動の中で検証した結果記録であり、忘れやすい自分のためのメモですが、少しでも皆様のお役に立てればと思い公開していきます。記述方法など試行錯誤しており随時更新するかもしれません。

## この記事のゴール：IDMC データ統合における Sourceデータオブジェクトのパラメータ化手段が解るようになる
共通のデータ連携処理を作り、データソースに当たるファイル・テーブルなどを実行時に動的指定したい場合があると思います。IDMCのデータ連携ではパラメータを利用して実行時に動的にソースデータを指定する事が出来ます。その具体的な設定例をメモしておきます。接続自体のパラメータ化は今回は扱いません。

尚この記事の内容は、R41 で検証しています。

### 具体的な手順
まずは普通に加工変換を含めたマッピング全体を作成し動作確認を行い、最後にソース部分をパラメータ化します。必要に応じて元マッピングをコピーして編集するのも良いですね。何かあったときのため元ネタを残しておく方が安心です。

今回の対象マッピングはこちら。先日の記事で作成したGoogle Big Queryへのデータ投入処理です(動作確認済み)。このマッピングのSourceとなるファイル名をパラメータ化して行きましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/21c1ac38-eab9-0517-9d3b-d46f07e4317f.png)

#### 1. ”入力パラメータ”を作成
パラメータパネルを表示させ、”入力パラメータ"の新規追加(＋ボタン)をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/a49d2e8b-4e65-9334-3084-c8468a3573c0.png)
表示される”新規入力パラメータ”ダイアログでパラメータを作成します。以下の箇所を設定します。
- 名前：パラメータ名。
- タイプ：データオブジェクト を指定します。
- 実行時にパラメータのオーバーライドを許可する：チェック  ・・ 実行時にパラメータを上書き可能にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/1cb47e23-6a6e-16ba-83aa-18661e5e33f3.png)

#### 2．Sourceトランスフォーメーション の ソースをパラメータ化
Sourceトランスフォーメーションのソースプロパティで、以下のように作成したパラメータを読み込むように設定変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/e8f4ee5b-9536-45ba-07ce-ce47643bfd24.png)

マッピングで必要な設定は上記まで。このマッピングを実行するマッピングタスクを作成します。

#### 3. マッピングタスクの設定
マッピングでSourceデータをパラメータ化した為、マッピングタスクでは実行時のSourceデータを指定するタブが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/9e0e36c9-7809-4596-9dc8-b57c17ec1e28.png)

まずはデフォルトで利用されるSourceファイルを指定します。実行時に上書きできるのでここのデータは仮指定のような形となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/99d512d8-5e9d-6fe4-1758-c817793e1cd8.png)

上記まで設定すればマッピングタスクとして保存でき、完成となります。


## (補足)パラメータを指定して実行してみる
パラメータを動的に指定して実行する手段はいくつかありますが、今回はタスクフローにしてRestWebServiceとして実行してみました。
詳細は割愛(別途記事にするか検討中)しますが、、

こんな感じ↓に、入力フィールドにパラメータ用の文字列を受け付けるタスクフローとして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/4fa5d718-8291-0073-041a-d3d98df0534c.png)
データタスクに今回作成したマッピングのマッピングタスクを設定し、、入力フィールドで作成したin_srcfilenameを渡すようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/9e503c3d-52f0-8603-c0d8-ca440bb0d14c.png)

保存し、パブリッシュして、発行されたサービスURLをコピーした後、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/219da990-eae2-f6ef-57d5-52242dc2c1f2.png)
そのURLをブラウザから呼出、実行してみます。そのときにパラメータとしてソースファイル名を渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/c621c24c-b7d7-3953-a514-188effbb5d1c.png)

CAR_SALES_202303.csv と言うファイル名を指定して実行します。モニタで確認すると無事成功しました。よかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985453/34fd8c3a-1b95-33d0-c3bd-064c71d8a419.png)

以上、検証結果を記述してみました。何かのお役に立てば幸いです。
gcloudを叩くその前に

短文のTipsです。
どのプロジェクトに対して操作をしようとしているのか、確認してからにしましょう！

僕(Mac利用)は以下のようなエイリアスを登録しておいて、最初にactive-gcloudによって、どのプロジェクトが今アクティブになっているのかを確認するようにしてます。

```
% alias active-gcloud="gcloud config configurations list | grep True | awk '{print \$4}'"
```

こんな感じでプロジェクト名が意図したものかをチェック。
```
 % active-gcloud                                                                          
project-hogefuga
```

direnvで設定するようにもしているのであんまりミスは起こりにくいんですが、なんか不安なのでその日の最初の作業や環境切り替えたときは一応叩くようにしてます。

もっと作り込まれてる方もおられるかもですが、手軽にできるこのTipsが、どなたかの事故を減らすことに繋がれば！
C#初心者による繰り返し処理メモ

初心者のForeachとWhileの使い分けメモです

・Foreachは中のデータを全て取り出したい時
・Whileはbreakで処理を抜けたい条件はある
　又は要素数が不確定な際に使用します。

個人的にはこんなイメージです。
正直違いが分からないし意味わかりませんでした。

一先ずはFor文から

        private void button1_Click(object sender, EventArgs e)
        {
            int sum = 1;
            for (int i = 1;i<5;i++)
            {
                sum = sum * i;
                Console.WriteLine(sum);
            }
        }
結果 1 2 6 24
カウントを保持し、そのカウントが抜けたら処理が終了します。

次にForeach文

        private void button1_Click(object sender, EventArgs e)
        {
            string[] array = new string[5] { "あ", "い", "う", "え", "お" }; 
            foreach (var arr in array)
            {
                Console.WriteLine(arr);
            }
        }
結果 あ い う え お
配列の中身を1つずつ取り出し、中身が無くなったら終了します。

最後にWhile文

        private void button1_Click(object sender, EventArgs e)
        {
            int i = 0; 
            while(true)
            {
                if(i == 5)
                {
                    break;
                }
                i++;
            }
        }
結果 iが5になった場合、処理を抜けます。
whileの中をtrueで記載する際はbreakを忘れずに置き、無限ループに気を付けましょう。

また、実際の使用例ですが
※List<string> lines = new List<string>();　と上で宣言します。

            using (StreamReader reader = new StreamReader(".txt"))
            {
                //全て取得
                while (!reader.EndOfStream)
                {
                    var txt = reader.ReadLine();
                    lines.Add(txt);
                }
            }
StearmReaderにてEndOfStream(データがなくなるまで)リストに取得します。
foreachでは中身のデータが確立してる際に、不確定な場合はwhileを。

使い方は色々あるので、色々試してみてください。
【Laravel】テスト環境を実装する

## はじめに
- テスト環境といってもDB設定などは今回は触れない(まだ理解が浅い)
- テストを行ううえで必要なファイルなどを準備する段階の記事
- テスト始めたてなので備忘録を兼ねて、どんどん追記をしていく予定

## テストをする目的・意味
https://qiita.com/yastinbieber/items/c818b60678ff9849d0ce

https://zenn.dev/tis1116/articles/bef862a5754187

https://media.wemotion.co.jp/class-diary/%E3%80%90qa%E3%80%91%E3%83%86%E3%82%B9%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E5%BF%85%E8%A6%81%E6%80%A7%E3%81%A8%E3%81%AF/

## テストの準備
### テストファイルを作成する
実際にテストを書いていくファイルを作成する。
```terminal
$ php artisan make:test UserTest
```

`tests/Unit`ディレクトリに作成したい場合はオプションで付け加えることができるが、今回はFeatureメソッドに足していくのでつけません。

上記コマンドを打つと、テストファイルが作成されるのでそこにテストを書いていく。

```hogeControllerTest.php
<?php

namespace Tests\Feature;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 基本的なテスト例
     *
     * @return void
     */
    public function test_basic_test()
    {
        $this->assertTrue(true);
    }
}
```

### テストの実行
下記コマンドでテストを実行させることができる。
```
$ php artisan test
```

### 参考
https://readouble.com/laravel/9.x/ja/testing.html
Cloud Run上にデプロイしたAPIサーバーが400 Bad RequestのYour client has issued a malformed or illegal requestを返す

ログにエラーが出力されず厄介な問題だったため共有します。

## 概要
GCPのCloud Run上にデプロイしたRuby on RailsのAPIサーバーにて、リクエストボディを含むGETリクエストのAPIを叩いたところ
`Your client has issued a malformed or illegal request`
と記載されたHTMLが返ってきました。以下HTMLを表示した画面です。
![スクリーンショット 2023-02-02 19.27.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153308/0b2dc917-9ccd-30b4-c6cc-cb92e6aed5e4.png)

## エラー詳細
ローカルでは問題なく動いており、Cloud Runにデプロイした本番環境のみで上記エラーが起こります。
Cloud Run上のログにはAPIが叩かれたことすら表示されていなく、リクエストボディを空にすると初めてログが表示されます。

## 原因
Cloud Runのようなクラウド上に構築されたサーバーを使用する場合、REST APIの原則に基づいて不自然なリクエストを弾く仕様がAPIサーバーでのリクエスト前段に構築されているようです。
今回の場合は、
**GETリクエストはURIに組み込まれた情報のみを使用するべきであり、リクエストボディ等を含むべきではない**
という思想に基づいた仕様がGCP上で適用されており、自身で構築したAPIサーバーに到達する前に弾かれていたことになります。
リクエストボディを含む場合はPOSTリクエストとしてAPIを作成しましょう。


## 参考
[python 3.x - デプロイされたサービスに到達せずに Cloud Run リクエストがエラー 400 をトリガーする](https://stackoverflow.com/questions/64336060/cloud-run-requests-triggers-error-400-without-reaching-deployed-service/64336402#64336402)
ベジェ曲線を用いたドリフトイージングの提案及び実装

　アニメーションにおいて、イージングは細かい味付けをするのに重要です。
　代表的なイージングとして、

- `Sine`
- `Cubic`
- `Quint`

　等がありますが（詳しくは https://easings.net/ja 参照）、より細かい表現をするために `Drift` というイージング関数を考案・実装しました。

# なにが出来るのか

　ある点まではイージング的な動きをし、ある点からは等速直線運動をして目的地に達する、という動きを表現できます。（最初がイーズアウトの時は）加速した後その勢いで滑っているように見えるので、`Drift` という名称をつけました。

　単一のイージング関数ではなく、運動が切り替わるポイントごとにイージング関数の形が変わります。そのグラフをまとめたものが以下になります。　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/16cdd37b-2592-8d07-7c6d-7b135713ab58.png)

（●は等速直線運動に切り替わるポイント）

　同様の動きを実装したり計算したりしている人は絶対にいると思いますが、理論的な背景をまとめたものはないので、ここで私がそれをまとめて、ドリフトと名付けたいと思います（既にこういう名前がある、というものがあったらすいません）。

# 実装の気持ち

　経過時間割合を $t (0 \leq  t \lt 1)$ 、到達割合を $r (0 \leq r \lt 1)$ とします。

　イージング関数は $r =f(t)$ という陽関数として定義することができます。

　等速直線運動に移るまでの時間割合を $x$、その時の到達割合を $y$ とします。

　後半の等速直線運動はけっこう簡単に求められます。

　$(x,y)$ と $(1,1)$ を結ぶ直線になるので、

```math
r = \frac{1-y}{1-x}(t-1) + 1 \\
= \frac{t-ty+y-x}{1-x}
```

　問題は前半で、**後半に滑らかにつながるようなイージング** を実装する必要があります。

　この関数を $g(t)$ とすると、

```math
r = \left\{
\begin{array}{ll}
g(t) & (t \lt x)\\
\frac{t-ty+y-x}{1-x} & (x \leq t)
\end{array}
\right.
```

　となります。

# ベジェ曲線

　「滑らかにつながらせる」ために、**ベジェ曲線**を使うことを考えます。

　イラレとかでよく使われるベジェ曲線は、正確には 3 次のベジェ曲線であり、他にもベジェ曲線は色々あるのですが、今回もこれを使うのがわかりやすいので以降は 3 次のベジェ曲線をベジェ曲線と呼ぶことにします。

　ベジェ曲線は、ハンドルと接線の傾きが一致するという性質があるので、

- 始点 $P_0$ ... $(0,0)$
- 始点ハンドル $P_1$ ... $(0,0)$
- 終点ハンドル $P_2$ ... $(x,y)$ と $(1,1)$ を結んだ直線とグラフの軸の交点
- 終点 $P_3$ ... $(x,y)$

　というベジェ曲線を書けば要求を満たせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/0fefc981-fa03-e62f-3570-bb6b13218fcb.png)



　$P_2$ の位置は、

```math
P_2 = 
\left\{
\begin{array}{ll}
(0,\frac{y-x}{1-x}) & (y > x)\\
(\frac{x-y}{1-y},0) & (y < x)
\end{array}
\right.
```

　となります。

　ベジェ曲線は媒介変数 $q$ を用いると、

```math
B = (1-q)^3 P_0 + 3(1-q)^2 q P_1 + 3(1-q)q^2 P_2 + q^3 P_3
```

　なる $B$ を $0 \leq q < 1$ の範囲で動かした時の軌跡となります。この媒介変数を解いて、$r = g(t)$ という陽関数の形に直す必要があります。$P_0$ と $P_1$ は $(0,0)$ なので無視してもよいですが、それでも 3 次式が残ります。

# 二分探索

　一般に 2 次以上の媒介変数を解析的に解くのは難しいですが、今回は単調性があるので二分探索を用いて高速に、ある $t$ に対する $q$ を求めることができます。許容誤差のオーダーを $\frac{1}{N}$ とすると、総当りでは $O(N)$ の計算量がかかりますが、二分探索であれば $O(\log{N})$ で済むので、厳しい許容誤差（より正確な値）でも高速に求めることができます。$q$ が決定できれば、$r$ は媒介変数を用いて直に計算できます。

　以上の処理をプログラムに直したものが以下になります。

```python

def Drift(t, x, y):
    if x == 1 and y == 1:
        return t
    if x > y:
        hy = 0
        hx = (x-y)/(1-y)
    else:
        hx = 0
        hy = (y-x)/(1-x)
    if t >= x:
        return (t-t*y+y-x)/(1-x)
    else:
        ng = 0
        ok = 1
        while abs(ng-ok) > 1e-10:
            mid = ng + ok
            mid /= 2
            criteria = 3*(1-mid)*mid*mid*hx + mid*mid*mid*x
            if criteria >= t:
                ok = mid
            else:
                ng = mid
        return 3*(1-ok)*ok*ok*hy + ok*ok*ok*y
```

# 結論

- イージングの表現力を高めるためにドリフトを考案
- ベジェ曲線を用いてドリフトを実装
- ベジェ曲線の計算を、二分探索を利用して高速化
受信した添付ファイルをGoogleドライブに保存するGAS




# スクリプトは V8 ランタイム設定
[プロジェクトの設定] で V8 ランタイムを無効にしします。

# ライブラリ設定
スクリプトID：
1xIy9FJeS3UtzAAW1j5fK2dZaiWxCdfy8cPT6yIdkfJSlBv7z7bxMmQZl

```javascript
var searchCondition = 'is:unread has:attachment subject:{' + "【件名】" + '} replyto:{' + "メアド@×××.com" + '}'; //検索条件（添付ファイルあり）;
var FOLDER      = DriveApp.getFolderById('保存先フォルダID'); //保存先フォルダID
var POSTURL     = "WebhookのURL"; //通知先チャットのURL
var pass        = "Password"

function getNewMail() {

  var threads = GmailApp.search(searchCondition, 0, 1); // search件数
 
  for (var i = 0 ; i < threads.length; i++) {
    var msgs = GmailApp.getMessagesForThread(threads[i]);
 
    for (var j = 0; j < msgs.length; j++) {
      var attachmentDate    = Utilities.formatDate(msgs[j].getDate(),"JST", "yyyy-MM-dd hh:mm:ss"); // 受信日時
      var attachmentFrom    = msgs[j].getFrom();           //送信元
      var attachmentSubject = msgs[j].getSubject();        //添付ファイル（タイトル）
      var attachments       = msgs[j].getAttachments();    //添付ファイル 
      
      var createFiles = FOLDER.createFile(attachments[0]);
      var zipfileid = createFiles.getId();
      // ZIPファイルを解凍
      var blob = DriveApp.getFileById(zipfileid).getBlob();
      var res = UnzipGs.unzip(blob, { password: pass }); // or UnzipGs.unzip(blob); 
      // ZIPファイル中のファイル
      var flsts = "";
      for(var k = 0; k < res.length; k++){
        var newFolder = FOLDER.createFile(res[k]);
        flsts = flsts + "\n" + "filename: " + newFolder.getName() + "\n" + "URL : " + newFolder.getUrl() + "\n";
      }

      if (flsts !== ""){
        createFiles.setTrashed(true); // ZIPファイル削除
        // メッセージ作成
        var msgbody = attachmentDate + "\n" +
                      attachmentSubject + "\n" +
                      "保存先フォルダのURL： " + FOLDER.getUrl() + "\n" +
                      flsts ;
        postoptions(msgbody);
      }
    } 
    // スレッドを既読にする
    threads[i].markRead();
  }
}

/**POSTメソッドのオプション*/
function postoptions (msg) {
  var options = {
    'method'  : 'POST',
    'headers' : {'Content-Type': 'application/json; charset=UTF-8'},
    'payload' :JSON.stringify({'text' : msg}),
    "muteHttpExceptions" : true
  }
  //通知を送る
  var response = UrlFetchApp.fetch(POSTURL, options); 
  try{
    // 通知
    if (response.getResponseCode() == 200){
      //判断フラグ
      response_flg = 0;
    }
  } catch (e){
    response_flg = 1;
    console.log("通知エラー" + e.messages); 
  } 
  return response_flg;
};
```
プロジェクト名やソリューション名のリネーム方法いろいろ


初期に命名したプロジェクト名やソリューション名を変更することになったので、まとめます。

下手に変更すると色々と不具合がでてしまうため、
他サイトと見比べる等して、気をつけて実行してください。

抜けがあったら申し訳ございません。

使用環境：
VisualStudio 2017
C#

# 変更について

リネームする箇所は大体、
- ソースコード
- visualstudioにあるソリューションエクスプローラー
- フォルダが実際に置いてあるエクスプローラー

です。

ソリューションエクスプローラーのフォルダを右クリックしてリネームしていくのですが、下から二番目(プロパティの上)くらいに、**エクスプローラーでフォルダーを開く**という便利な機能があるので活用してください。
<br>
## ソリューション名の変更

``visualstudio`` ：ソリューションエクスプローラーの一番上のファイルを、右クリックして名前を変更からリネーム


``エクスプローラー``：おそらくvisualstudioエクスプローラーと連動されるので、不要だったはず…。.slnの拡張子のついたファイルを確認して、変更されていなければ右クリックしてリネーム
<br>
## プロジェクト名の変更

``visualstudio`` ：ソリューションエクスプローラーのすぐ下にある拡張子のないフォルダを右クリックしてリネーム

``エクスプローラー``：エクスプローラーでフォルダーを開くをした後に、**一つ前の階層に戻って**プロジェクトフォルダをリネーム
※リネーム前にvisualstudioを終了させる。

再びvisualstudioを起動させ、該当のソリューションファイルを開く。

プロジェクトフォルダが利用不可になってしまうので、一旦右クリックで削除する。

次にソリューションエクスプローラーの一番上のファイルを右クリックして、追加 → 既存のプロジェクト → プロジェクトフォルダの中に入っている.csproj拡張子のついたファイルを選択する。

<br>

## namespace名の変更

``ソースコード``：ソースコード内のnamespace名を書き換えればOK。その際変更したいnamespace名の上で右クリック → 名前の変更で、ウィンドウが表示されオプションが選べる。
<br>

## class名の変更

``visualstudio`` ：.csファイルを右クリックでリネーム

``エクスプローラー``：おそらくvisualstudioエクスプローラーと連動されるので、不要だったはず…

``ソースコード``：ソースコード内のnamespace名を書き換えればOK。その際変更したいnamespace名の上で右クリック → 名前の変更で、ウィンドウが表示されオプションが選べる。
<br>

## アセンブリ名や名前空間名の変更

これを変更することで、.exeファイルの名前が変更される。

こちらはvisualstudioのプロパティから設定する。

リューションエクスプローラで変更したいプロジェクトを右クリックし、プロパティ → アプリケーションを選ぶ。

下記に入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3069823/d2a12e16-3e1e-84ae-be69-1ed463d9466c.png)

<br>


### 参考

- https://www.ipentec.com/document/visual-studio-change-project-name
- https://atmarkit.itmedia.co.jp/ait/articles/1804/18/news019.html
【テックジム無料講座】Ruby on Rails講座 ＜問合せフォームを作ろう＞の感想

テックジムが無料で開催している、Ruby on Rails講座 ＜問合せフォームを作ろう＞をオンラインで受講してみました。Rubyを勉強した経験が無く、動画の通りには出来たものの、何をやっているのか良く解りませんでした。AWS Cloud9を利用しているので、ウェブベースで受講出来るのが便利だと思いました。現在の私の場合、テックジムさんのRuby on Rails本講座を受講する前に、progate等で、Rubyの基礎を学ばないと、独習は難しいと感じました。

<a href ="https://youtu.be/50VFge6ntO4">1-0 環境構築編</a>
<a href ="https://youtu.be/yH66nPLTW5U">1-1の解説動画</a>
<a href ="https://youtu.be/uG1e37lCcGg">1-2の解説動画</a>
<a href ="https://youtu.be/hU95_JKZO9E">1-3の解説動画</a>
<a href ="https://youtu.be/NksgbGflSoE">1-4の解説動画</a>


<a href ="https://github.com/techgymjp/techgym_rails_open/blob/master/RailsCourse01_1.pdf">テキスト</a>
Ubuntu OSをインストールしたら無線LAN/有線LAN/キーパッドが使えない

# はじめに

2月から転職をして新しい環境で働くことになりました
社内ではエンジニアはUbuntuのPCを利用しているとのことだったので、Windowsをクリーンアップして、Ubuntuに変更したときにつまづいたことをまとめます

# 問題

以下のサイトを参考にUbuntuのインストールを行いました

https://color-code.net/post-2783

無事Ubuntuの起動までいったのですが、何故か無線LANがつなげませんでした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/3598561b-4c7a-60d4-fbf8-c6c2073902f2.png)

本来はこの扇のマークがあるはずなのですが表示されません
設定を確認してもVPNの設定のみで認識されていないようでした

いろいろ調べていると有線LANをつなげて、無線LANを使えるようにドライバーをインストールしていましたが、私の環境では有線をつなげてもつながらず、`apt-get updaste`すらできない状況でした

またPCについているトラックパッドも機能していませんでした

# 解決方法

`Ubuntu 20.04LTS`
↓
`Ubuntu 20.04.5LTS`

にOSを変更したところ治りました。Ubuntu20.04.5はドライバも含まれているようです

https://releases.ubuntu.com/focal/

# おわりに

入社2日目にして何もできずこのあとの研修も参加できないかと思いとても焦りました
チームの方々に感謝です。

# 参考

https://color-code.net/post-2783

https://releases.ubuntu.com/focal/
ILI9341ライブラリ描画高速化

## 概要
ILI9341ライブラリはピクセルの書き込みを行う際、SPI通信を毎回開け直している。
そのため無駄な通信が多く、非常に遅くなっている。(下図)
ピクセルに書き込みを行っている関数を探し出し、それを使って描画コードを自作することで描画を高速化する。
なのでライブラリ内の図形描画や文字描画は早くならない。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123751/a61f079a-afe0-7fa0-b159-be49dd41fcee.png)
(昔作った図)

他の液晶ライブラリも共通な部分が多いので、同じように高速化できる...かもしれない

## 環境
マイコン:teensy4.0


液晶:ILI9341搭載2.8インチSPI制御タッチパネル付TFT液晶　MSP2807
　https://akizukidenshi.com/catalog/g/gM-16265/

ライブラリ:teensy用ILI9341ライブラリ ILI9341_t3.h (teensyduino入れた時についてきた)

## 手順
### 描画関数を特定する
105行あたりに drawpixel()関数がある。
```C:ILI9341_t3.cpp
void ILI9341_t3::drawPixel(int16_t x, int16_t y, uint16_t color)
{

	if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
		return;

	beginSPITransaction(_clock);
	setAddr(x, y, x, y);
	writecommand_cont(ILI9341_RAMWR);
	writedata16_last(color);
	endSPITransaction();
}
```
1pxだけ書き込んで、通信を終了している。

### 使う関数をpublicにする
drawPixel()内の関数を使いたいので使えるようにコードを改編する。
宣言されている場所に行き、protectedを消してpublicにしてしまう。
301行あたり
```C:ILI9341_t3.h
    ....
    uint16_t measureTextWidth(const char *text, int chars = 0);
	uint16_t measureTextHeight(const char *text, int chars = 0);
	int16_t strPixelLen(char *str);

	// protected: ←←←←←←←←←←←←←←←←←←←←←←←←←ここ
	unsigned long _clock = ILI9341_SPICLOCK;
	int16_t _width, _height; // Display w/h as modified by current rotation
	int16_t cursor_x, cursor_y;
	uint16_t textcolor, textbgcolor;
    ....
```
### 描画コードを自作する
canvasに描いたものを出力する。
canvas[x][y]=tft.color565(r,g,b); で描ける。
```C:main.ino
#include <ILI9341_t3.h>
#include <SPI.h>
#define TFT_DC  9
#define TFT_CS 10
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
void setup(){
    Serial.begin(115200);
    tft.begin();
    tft.setClock(79999999); //ここは定格越えてて、動作するギリギリにしてある
    tft.setRotation( 1 );
    tft.fillScreen(ILI9341_BLACK);
}

short canvas[320][240];//二次元配列

void loop(){
    static int count=0;
    static int fps=0;
    count++;
    //draw canvas
    tft.beginSPITransaction(tft._clock); //描画開始
    tft.setAddr(0, 0, 320, 240); //書く範囲指定
    tft.writecommand_cont(ILI9341_RAMWR); //書き込みコマンド？？？知らん
    for(int y=0;y<240;y++){
      for(int x=0;x<320;x++){
          if(x==319 && y==239){//最後はwritedata16_last
                tft.writedata16_last(canvas[x][y]); 
                tft.endSPITransaction(); //描画終了
            }
          else tft.writedata16_cont(canvas[x][y]); //ピクセル(x,y)描画
          canvas[x][y]=tft.color565(0,0,0); //黒塗り初期化
      }
    }
//    while(millis()-ftime <= 33); //fps固定
    if((millis()-startTime) >= 1000){ //fps計算
        startTime = millis();
        Serial.print(count);
        Serial.print("FPS ");
        fps=count;
        count=0;
    }
}
```


## おわり
書き込んでみる
SDカードから画像を読み込むコードを書いた。
![index.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123751/988f71aa-76df-6aa9-d0fd-8eda5a0965bf.gif)
もともと15fpsだったものが、45fps出るようになった。

せっかくなら60fps出したかったけど... ILI9341側がギリギリなのでできるのか分からん
1f前のcanvasと比較して、変化がないところはスキップする...とか？(FPS不安定になりそう)

↓これ作る時に使った

https://youtu.be/UFg4_pCa7yU


更新日 2023/02/02
【Unity】OverlayのCanvasにParticleを表示する方法

# OverlayのCanvasより前にパーティクルを出したい！
UnityでuGUI上にパーティクルを出したい時、すでにOverlayのCanvasがあると、RenderModeをCameraにしても最前面には出てくれることはなく、Overlayに直接パーティクルを出すこともできないので、もうだめだ！おしまいだ！と思っていましたが、表示する方法を見つけたので解説していきたいと思います。
ただし、かなり遠回りなうえ、使い勝手は劣悪かつ設定が面倒です。なのでほぼ私的な備忘録です。

## RenderTextureを用意する
Asset→Create→Render Texture　(たぶん真ん中あたりにあります)
名前は任意なので分かりやすくつけましょう

## Cameraを用意する
パーティクルを表示するための専用のカメラを用意します。
まずカメラの設定ではないですが、LayerにParticleを追加しましょう。

### Layerの設定
InspectorにLayerがあるのでクリックして、一番下のAdd Layerを押します。
User Layer の任意の場所にParticleを入力。
Particleでなくても任意の名前で大丈夫ですが、この記事ではParticleとしておきます。

### Cameraの設定
Clear FlagsをSolid Colorに
Backgroundのα値を0に
Culling MaskをParticle
いくつか飛ばして
Target Textureに作成したRenderTextureを入れます。

ComponentにAudio Listenerがついていると思うのでこれはRemove Componentしましょう。
すると下図のようになっていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122922/cf588a88-1c46-cc72-ba75-add213717f05.png)

これで、このカメラは作成したRenderTextureに対してパーティクルのみ映した内容を返します。

## Particleの設定
次にCamera下にParticle Systemを作成します。
任意ではありますが、X:0 Y:0 Z:10にしておくと大抵いい感じにはなります。
近すぎるとうまく表示されないこともあるので……
### Layerの設定
忘れてはならないのがLayerの設定です。
Particleにしておかないと、作成したカメラの撮影対象にならないので映りません。

### Materialの作成
表示するパーティクルにはMaterialの設定が必要です。
Asset→Create→Material
作成したMaterialを選択して、ShaderをStanderdから
Moblie→Particles→Alfa Blend
に変更します。
Textureを選択し、パーティクルのテクスチャを選択。
この辺りは任意ですが、まずちゃんと表示させることが目的なので、まずやるだけやってみましょう。
設定をし終えたら、このMaterialをドラッグアンドドロップで作成したParticle Systemに入れます。

#### Materialがないとうまく出ない
この記事で残している問題として、Materialを設定してあげないと表示がうまくいかないことです。
原因をよく理解していないため、この辺りしっかり理解したいですね。

## uGUIとして表示する
### Canvasを用意する
すでにあるならそれでいいです。タイトルにある通りRender ModeがScreen Space - Overlay上でParticleを表示する方法なので。
ただ表示順の都合で、出ない可能性があるので今回は新しく用意しましょう。
・Render ModeをScreen Space - Overlayに
・Sort Oderを既にある他Canvasより大きい数字に（今回は1にします）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122922/26aa12ad-a343-ae2c-c5d5-f9d91dd7082a.png)


### RawImageを使って表示
ここまでくれば後はCanvasにRawImageを作成するだけです。
作成したRawImageに対して、作成したRenderTextureを設定します。


## これで完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122922/0d0fe7d0-c05b-6cab-072b-5cc567b3c733.png)
画像の通り、最前面に表示されます。ここまでの設定だと、少し小さすぎたりしますがそのあたりの調整はご自身で……。
FileReader

FileReader is subclass of InputStreamReader
read() returns char value or  -1 if eof occur.

```java
public class Outer {
    public static void main(String[] args) {
        FileReader r = null;
        try {
            r = new FileReader("C:\\dirtest\\testmakefile.txt");
            while(true) {
                int i = r.read();
                if(i!=-1) {
                    System.out.print( Character.toChars(i));
                } else {
                    break;
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if(r!=null) r.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}
```
```
hello
bye
```
try with resourceを使うとclose()を書かなくてもblockが終了時に
自動でclose()してくれる
```java
public class Outer {
    public static void main(String[] args) {
        try {
            FileReader r = new FileReader("C:\\dirtest\\testmakefile.txt");
            try (r){
                while(true) {
                    int i = r.read();
                    if(i!=-1) {
                        System.out.print( Character.toChars(i));
                    } else {
                        break;
                    }
                }
            }
        } catch (IOException ex ) {
            ex.printStackTrace();
        }
    }
}
```
EC2に固定のパブリックIPアドレスを割り当てる

## 概要
もともと認知していたcloud9のIPが変動し接続できないということがありました。
このような問題に対処するために、ec2にElastic IPアドレスを割り当ててあげます。
cloud9の起動しているec2インスタンスにElastic IPを付与することで、cloud9のパブリックIPを固定することができます。

## 目次
1. なんでElastic IPを付与するのか
1. 手順

## 1.なんでElastic IPを付与するのか
停止したインスタンスを再起動した場合、新しいIPアドレスが割り当てられる可能性があります。意図せずにIP アドレスが変動すると、利用者にとっては参照できないなどの不利益を被ります。
これの対策として、Elastic IPアドレスをインスタンスに割り当てます。Elastic IPは、単一のIPアドレスを継続してインスタンスに関連付けすることが可能です。これによって、Elastic IPの関連付けられたインスタンスを停止/再起動した場合でも、IPアドレスの意図しない新しい割り当てを抑制することができます。

> Elastic IPについて ー公式ー 
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html

## ２.手順
本章では、Elastic IPをEC2インスタンスに関連づけて、Cloud9から付与されたパブリックIPアドレスを確認する方法を記載します。

まず、Elastic IPの設定をしていきます。マネージメントコンソールの検索画面にElastic IPと検索して以下の画面に移動してください。
![①elasticip検索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/5dd7f11b-3270-d02b-3e96-f7077f473443.png)

画面右上のElastic IPアドレスを割り当てるを押下。

![②elasticip設定１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/8572ede4-a42a-f255-0bda-1451e9ef2ec4.png)

ここでは、ネットワークボーダーグループを選びます。私は東京リージョンなので、ap-northest-1を選びます。他は特にいじらなくてokです。

![③elasticip設定２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/995c3446-298e-64d8-e7dd-afc9d6621776.png)

上記の画面で、Elastic IPアドレスが出力されました。ここでは、インスタンスとプライペートIPアドレスの欄に情報を入力していきます。入力が完了したら関連付けるを押下。

![④elasticip設定完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/99f6f970-f50d-db1d-fea4-d0abd986e6c9.png)

IPアドレスを割り当てられたら、右上のElastic IPアドレスを関連付けるを押下します。

![⑤IP確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/90f5bb9b-5ce2-e5d9-3312-17a69af4f877.png)

これでElastic IPアドレスがインスタンスに関連づけられたので、概要から、割り当てられたIPv4アドレスを確認します。先程表示されていたElastic IPアドレスが割り当てられていることがわかります。(黒塗りですいません)

それでは、Cloud9からもパブリックIPを確認したいと思います。
Cloud9を開いて、以下のコマンドをターミナルに入力します。
```terminal:IPv4確認
curl http://169.254.169.254/latest/meta-data/public-ipv4
```
以下のように、設定したIPを確認することができるはずです。（赤塗りの部分にIPが出力されます）
![⑥cloud9で確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/02a141e0-db01-2b68-cca6-3feb7f6ebcf5.png)


以上でIPアドレスを固定することができました。試しにインスタンスを停止/再起動してみてください。パブリックIPアドレスは変動していないと思います。cloud９でも同様です。

## おわりに
これでインスタンスを停止/再起動しても、パブリックIPは変動しないようになりましたね。
また、Elastic IPは割り当てないと料金が発生するので注意が必要ですね。
初めて誰かのTaskを解決するまでの５ステップ

Creatorには伝わるTableauですが、一般にはまだあまり知られていません。
特に中小企業・個人店など、**データはあるが可視化できていない**ところは多いと思います。

そこで、個人店を営む方のTaskを解決したプロセスを、時系列順にまとめてみました。
先方はこれまでTableauに触れたことがなく、今回初めてVizを体感された方です。

少しでもお役に立てれば幸いです！<br><br>
## １．必要なデータをイメージ
まずヒアリングの前準備として、あると嬉しいデータを書き出しました。
「**何が分かると分析できそうか**」を軸に、必要なデータの候補を考えていきます。
例えば下記のようなデータがあると、分析できることが多いと思います。

* レジデータ
* 決算書（税務申告を行う資料）
* 売上規模がわかるもの

特にレジデータには、売上が計上された日時・時間帯・商品など、非常に多くの情報が詰まっています。**オープンデータ**と合わせれば、気候と紐付けることも可能です。
もしレジをデジタル化している店舗であれば、ぜひ入手したいデータの一つです。
## ２．ヒアリング
続いて、先方とヒアリングを行います。
私は以下のアジェンダで進めました。

* データ分析の説明
* Tableauができることを紹介（Tableau PublicでViz紹介）
* データ分析で解決したいTaskの確認
* 使用するデータ・受け渡し方法の確認
* 次回打ち合わせ（分析結果の報告）のアポイント

初めてデータ分析に触れる方だったため、シンプルな例を用いて**何ができるか**をざっくりとお伝えしました。具体的には「売上が計上された日時・商品から売上動向がわかる」、「曜日・時間帯・気象を組み合わせると回転数がわかる」といった内容です。
また完成品のイメージがつきにくいと考えたため、パブリッシュされているVizを目の前で動かして「**こんなことができます！**」と紹介しました。

説明とViz紹介でイメージを掴んでいただけたので、ここから「課題に感じていること・知りたいこと」をヒアリングしてTaskの確認を行いました。

* When（いつ）：日付（年月週）、曜日、時間帯、気象、温度（季節）、イベント
* Where（どこ）：掲載メディア、フロア
* Who（誰）：従業員（社員・アルバイト）、客層（男女）
* What（物）：商品、売上、利益、原価、集客数、予約数、勤続期間、客単価、人数

上記を一緒に見ていただきながら、「何ごとに何を見たいか」を探索しました。
**Tableauのデータペイン**を一覧にしたイメージです！

Taskの確認が完了したら、使用するデータの確認を行います。
１でイメージしたデータとTaskを基に「何のデータがあれば分析できるか」を擦り合わせました。
どうしても必要なデータがアナログだった場合は、自分で手打ちして落とし込みます。

最後に報告会のアポイントを取得したら、ここからViz作成に移ります。
## ３．データの整理
全てのデータにざっと目を通し「何の項目があるのか」を確認します。
重複しているデータ、不要であると明らかになっているデータの列は削除します。
シンプルな構造の場合は、変換できるデータであれば、Excelのみで整えることも可能です。

アナログデータをお預かりした場合は、自身で手打ちしてデジタルデータを作ります。
## ４．Tableauで分析
Taskの解決に向けて、**MECE**を意識しながらデータを分析します。
漏れなくダブりなくするため、Taskを頂点に置いたピラミッドを組み立てながら探索しました。
ここで「さらに表せた方が良いこと」を見つけたら、＋αとして分析・提案します。

今回はデータ内の期間中に変動する要因が多く、先方が「どの条件で可視化したいか」はあらゆるケースがあると考えたため、情報を絞れるようにフィルターを多く設置して連動させました。
「**比較したい項目は並べて出す、フィルターでノイズを消せるようにする**」を意識すると、探索型・説明型のどちらか、あまり迷いなく作成できると思います！

散布図の場合は「**原因を横軸に、結果を縦軸に**」を統一することで、思索が非常に楽になります。
## ５．分析結果の報告
アポイントまでに分析を完了し、実際に目の前でVizを操作して報告します。
私は以下のアジェンダで報告しました。

* 分析結果の説明
* Taskの解決策を提案
* Tableau Readerの紹介
* ＋αの提案

４でフィルターを多く設置したので、先方が可視化したい条件を訊きながら、目の前でVizを操作してお見せしました。結果が一目で分かるため、「それならこの組み合わせはどうだろう？」と様々な思索を**その場で**試すことができます。
最終的に「このデータも追加してさらに分析してほしい！」と追加要望をいただき、まだ見えていなかった新しいTaskを浮き彫りにすることもできました。

実際に手で操作していただくために、まずは無料の**Tableau Reader**を紹介しています。
また＋αの提案として、レジデータのさらなるデジタル化、Vizの自動化などもご提案しました。<br><br><br>
以上、初めて誰かのTaskを解決するまでの５ステップでした。

データを可視化して初めて見つけられるTaskが、あらゆる場所に眠っていると思います。
Taskを解決するための最もストレートな近道がデータドリブンだと思うので、ぜひ周囲を巻き込んで、気軽にTableauを活用してみてください！


最後に、今回の取り組みにご協力いただいた皆様へ、心より感謝申し上げます。
<br><br>
Laravelインストール時に出たzipのエラー解決備忘録

# 環境
・OS : Windows11  
・Composer : 2.5.1
・XAMPP : 8.2.0

# エラー
`composer create-project laravel/laravel:^8.* test`のコマンドで
インストールしようとした際に
`The zip extension and unzip/7z command are both missing`が下図のようにたくさん出て怖い
![2023_02_01_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240612/e3cba72f-5f46-8afa-3d8b-6fba9659127f.png)

# 解決法
・`php.ini`をVScode等で開く　　`C:\xampp\php\php.ini`にある

・`zip`を文字検索などで検索すると`;extension=zip`が出てくる

・この`;`を外し、`extension=zip`にして保存する
![php.ini - php.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240612/34f1cbb3-4cb7-99c5-2ab2-91a67eed87d2.png)

これで`composer create-project laravel/laravel:^8.* test`を実行するとスムーズにインストールできる。
File class

indicate directoryの配下のfile/directoryを表示するプログラム
Fileはfile path , directory pathをmanageする
listFiles()は指定ファイルの配下のファイルをarrayとして返す
listFiles()にFileFilterを指定するとfilterをかけた結果を返す

```java
public class Outer {
    public static void main(String[] args) {
        File f = new File("C:\\dirtest");
        FileFilter ff = pf -> {
            if(pf.isDirectory()) return true;
            if(pf.getName().endsWith(".java")) return true;
            return false;
        };
        method(f, "",null);
        System.out.println("---------------------------------");
        method(f, "",ff);

        File f1 = new File("C:\\dirtest\\testmakefile.txt");
        method2(f1);    
        File f2 = new File("C:\\dirtest\\test3dir");
        method3(f2);    
    }
    
    static void method(File pf, String indent, FileFilter ff) {
        //System.out.println(pf.getAbsolutePath());
        class SampleClass {
            File[]  method() {
                if(ff == null) return pf.listFiles();
                else  return pf.listFiles(ff);
            }
        }
        File[] fs = new SampleClass().method();
        for(File f:fs) {
            System.out.print(indent + f.getName());
            if(f.isDirectory())  System.out.println("   is directory.");
            else  System.out.println("    is file");
            if(f.isDirectory())  method(f, indent + " ",ff);
        }
    }
    static void method2(File pf) {
        try {
        if(!pf.exists()) pf.createNewFile();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    static void method3(File pf) {
        if(!pf.exists()) pf.mkdir();
    }
```
```
test2dir   is directory.
 subdir   is directory.
  sub2dir   is directory.
   testfile1.txt    is file
   testfile2.txt    is file
  testfile1.txt    is file
  testfile2.txt    is file
 testfile1.txt    is file
 testfile2.txt    is file
 testfile3.java    is file
test3dir   is directory.
testdir   is directory.
 subdir   is directory.
  sub2dir   is directory.
   testfile1.txt    is file
   testfile2.txt    is file
  testfile1.txt    is file
  testfile2.txt    is file
 testfile1.txt    is file
 testfile2.txt    is file
testmakefile.txt    is file
---------------------------------
test2dir   is directory.
 subdir   is directory.
  sub2dir   is directory.
 testfile3.java    is file
test3dir   is directory.
testdir   is directory.
 subdir   is directory.
  sub2dir   is directory.
```
PytestでPrivateメソッドを扱う時の備忘録

# 概要
- 単体テストを書く際に、Privateメソッドの呼び出しに苦労したので方法を書き下しておく。

# ケース１（通常呼び出し）
### テスト対象ファイル
```python:function.py
class Service:
    def __private(self, name):
        return name
```

### テストファイル
```python:test.py
from function import Service

def test_private():
    name = "Smith"

    s = Service()
    r = s._Service__private(name)

    assert r == "Smith"
```
```
[クラスのインスタンス]._[クラス名]__[Privateメソッド名]
```

# ケース２（Mockする場合）
### テスト対象ファイル
```python:function.py
class Service:
    def __private(self):
        return 1
    
    def no_private(self):
        return self.__private()
```
### テストファイル
```python:test.py
from function import Service
from unittest.mock import patch

def test_mock_private(method):
    s = Service()
    with patch.object(s, '_Service__private', return_value=3) as method:
        s.no_private()
        method.assert_called_once_with()
```

もしくは

```python:test.py
from function import Service
from unittest.mock import patch

@patch.object(Service, "_Service__private", return_value=3)
def test_mock_private(method):
    s = Service()
    s.no_private()
    method.assert_called_once_with() 
```

# ケース３（複数のメソッドをMockする場合）

### テスト対象ファイル
```python:function.py
class Service:
    def __private_1(self):
        return 1

    def __private_2(self):
        return 2
    
    def no_private(self):
        self.__private_1()
        self.__private_2()
```
```python:test.py
from function import Service
from unittest.mock import patch

@patch.object(Service, "_Service__private_1", return_value=3)
@patch.object(Service, "_Service__private_2", return_value=3)
def test_mock_private(method1, method2):
    s = Service()
    s.no_private()
    method.assert_called_once_with() 
```

# ケース４（テーブル定義をモックする場合）

```python:example.py
def test_add_new_table():
    td = Mock(TableDefinition)
    td.table_name = "table_name"
    patch.object(LocalDbService, "_Service__get_all_table_definitions", return_value=td)
```
vite.config.jsに.envの環境変数を読み込む

# 環境
Vite 4.0.0
Vue 3.2.45

# .envとpackage.json

--modeなしなら.env、--modeを付けて.env.hogeを読み込んだり。
``` package.json
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build_hoge": "vite build --mode hoge",
    "preview": "vite preview"
  }
```

環境変数の先頭には必ず「VITE」をつける必要あり。
``` .env
VITE_APP_PATH='/dist/'
```
```.env.hoge
VITE_APP_PATH='/hoge/'
```

# vite.config.js
defineConfig()をreturnする形に変更して、今回は以下のようにbaseキーに環境変数を設定した。
```vite.config.js
export default ({ mode }) => {
  process.env = {...process.env, ...loadEnv(mode, process.cwd())};

  return defineConfig({
      base: process.env.VITE_APP_PATH,
      plugins: [vue()],
      resolve: {
        alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
        }
      },
  });
}
```

npm run build、npm run build_hogeなど実行して、アセットのパスが変わってることを確認。
できました。

# 参考
https://stackoverflow.com/questions/66389043/how-can-i-use-vite-env-variables-in-vite-config-js
Green Xanax Online 

![CALLING - +1(786)8021504 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3105341/66051d70-cf65-7233-c037-f8d5a3936bf0.jpeg)





Green Xanax bar is a high-dose formulation for preventing and treating anxiety, mild insomnia, seizures, GAD, and phobia. It belongs to the class of drugs called benzodiazepines of Medium propensity. t belongs to the class of drugs called benzodiazepine, which works by activating certain neurotransmitters that can cause anxiety and allied condition. Xanax binds at the same spot where naturally occurring GABA aligns  <a href="https://onlinemedsguru.com/product-category/buy-green-xanax-bars-online/"> Green Xanax Bar</a>. Therefore, it is an effective first-line treatment for anxiety and allied condition.


Green Xanax Bar is a potent formulation that consists of 2mg of Alprazolam, and it is used both for therapeutic and nontherapeutic purposes(RECREATIONAL). In addition, it is also known as “ HULK XANAX “due to its potency and power. However, it is a high-dose drug; therefore, the risk of addiction, drug abuse, and misuse increases.

It comes with the imprint” S903 and two on the other side of the rectangle bar with grooves for ease of breakage. The effect of XANAX kicks in within an hour as it is quickly absorbed into the bloodstream <a href="https://greenxanaxbar.weebly.com/">Green Xanax bar</a>. 

What can be the possible side effects of the Green XANAX bar?
Green Xanax bars may induce some side effects, and these side effects will wash off in a couple of days. Some common side effects include :
 
  Drowsiness
  Dizziness
  Lack of energy
  Dry mouth

The severe side effect of Xanax is rare; therefore, it is important to manage the side effect if any serious side effect appears, as delay can injure your health.

Always follow the instruction of your prescribing practitioner, as your doctor will prescribe your dose as per the instruction of your doctor and as per the severity of your symptoms; therefore, it is important to take I exactly. You can break the bar into parts; each part will comprise 0.5 mg.
 In addition, do not increase OR decrease the dose on your own.
2e19を超える数値の保存

残念ながら、InfluxDBはまだ大きな数をサポートしていません。すべての整数を符号付き int64 データ型として格納します。 
int64 の有効な最小値と最大値は、-9223372036854775808 と 9223372036854775807 です。
詳細はhttps://docs.influxdata.com/influxdb/v1.6/troubleshooting/frequently-asked-questions/#what-are-the-minimum-and-maximum-integers-that-influxdb-can-store
AnimationDrawableでOutOfMemoryErrorと出会ったときに試したこと

メモです

setImageResource()が極端に重くなる。
`android:largeHeap="true"` は元々指定されていた。

# リソースの置き場を確認

画像のスケーリングが処理としてはかなり重いので適切な場所に画像リソースを置いておかないとメモリを消費しがち。
`drawable-XXdpi`にサイズごとに分けて置くか、-nodpi, -anydpiといったところに配置してスケーリングが発生しないようにする。
https://developer.android.com/training/multiscreen/screendensities

# 画像を解放して続行

重くなる処理がわかっているのでcatchして発生後の処理を書くことができる。
下の例では重い画像を解放してやって続行している。アニメーションは表示させないことになる。
OOMが実際に出るまでに数秒は重くて操作できない時間が発生する。
処理が続行した直後に別の画像の読み込みに失敗することがある。
もちろん推奨はできないけどAndroidCodeSearchで検索すると割とヒットしたりするやり方。

OutOfMemoryErrorはExceptionを継承したクラスではないのでExceptionでまとめてcatchしようとしてもできない

```kotlin
try {
    imageView.setImageResource(animatable)
} catch(e: OutOfMemoryError) {
    imageView.setImageDrawable(null)
    return
}
```

# 自作FrameAnimationクラスを作る

先達が数人いたのでそれらを参考に。別記事にまとめます。
https://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android
https://gist.github.com/miensol/f4d6aa65fb09d627ae7e

自作アプリの中でいい感じにデコードする処理の詳細↓
https://developer.android.com/topic/performance/graphics/load-bitmap

# 試してうまくいかなかったこと

## lowMemory検知

https://developer.android.com/topic/performance/memory#CheckHowMuchMemory
このへん

今回のケースではアニメーションの読み込み開始まではメモリ消費してないのでlowMemoryではfalseが返ってくるため回避不可だった。

## 空きメモリ量を取得して確認

OOMErrorのFatalログに確保しようとして失敗したメモリ量が出力されるので確認は可能なはず？
取得の仕方や取得できるメモリ情報にもいろいろあるらしくどれで判定したらいいかよくわからず。ちゃんと調べたら追記するか別記事にまとめます。


# 感想・その他

ハイエンド端末でも試験する方法が用意されていた
https://developer.android.com/topic/performance/memory-overview#stressapptest
[Swift] DateをExcelのシリアル値に変換する方法

# 数値の変換

次の変換式により、SwiftのDate型の値を[Excelのシリアル値](https://command-lab.com/tech/excel-sirial-number/)に変換する。

```swift
let dateTime: Date = xxxx
let serialValueForExcel = (dateTime.timeIntervalSinceReferenceDate / 86400) + 36892 + 0.375
```

- 86400：1日＝24時間＝24×60×60＝86400秒
- 36892：1899年12月31日から2001年1月1日までの日数
- 0.375：9×60×60/86400：日本の時差（UTC＋9時間）

※）~~なお、**dateTime**は2001年以降の日付であること~~ Excelの基準日以降の日付であればいつでも可

# 例

```swift
let now = Date()
//2023.02.02(木)17:44:05.917
print(now.timeIntervalSinceReferenceDate)
//697020245.917199
let serialValueForExcel = (now.timeIntervalSinceReferenceDate / 86400) + 36892 + 0.375
print(serialValueForExcel)
//44959.73895737499
```

↓Excelでミリ秒までちゃんと見えてます。

![スクリーンショット 2023-02-02 17.47.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/eba56dc5-a9df-aa0f-b08e-509ceaccced1.png)


# Excelの基準日

Excelは基準日として、デフォルトは、1899年12月31日（セル表記上は1900年1月0日）を0日とした通算日を採用している。オプション設定で、基準日を1904年に変更できる。
もし、1904年を基準日とした場合は、変換式の定数`36892`を`35430`にすること。

:::note warn
Excelは、デフォルトの基準日の場合に1900年の閏年の判定にバグがあることが知られている
https://learn.microsoft.com/ja-jp/office/troubleshoot/excel/wrongly-assumes-1900-is-leap-year
:::


以上
StreamDeckっぽいものを作る_0

最近周りがStreamDeckを使ってるみたいなので興味が湧いて見てみたら何か作れそうと感じたので見切り発車で作っていこうと思う。
開発メモ的に随時内容上げていく予定

とりあえずstreamdeckがどういうものかという認識
obs操作
他のファイル実行
オーディオ操作
Discord操作
ウェブブラウザ操作
以上のことがボタン一つで操作できる
Visual Studio CodeでPythonの自動校正を行う

Pythonのコーディング規約で、今現在主流である[PEP8](https://pep8-ja.readthedocs.io/ja/latest/)。
この書き方を意識していても、全て沿った書き方を意識的にするというのも大変。
合っていない部分を表示するExtensionもありますが、それを自分で全部直すのも大変。
なので、自動校正ツールを使って、自動で直せるものは任せてしまいます。

# 設定

1. autopep8をインストール
  Extensionからautopep8をインストールします。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/dde7eb97-18c6-161c-6e68-fd91d477790f.png)
2. 設定を変更する。
  VSCodeの左下の歯車マーク（Manage）をクリックし、さらに「Settings」を選択します。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/e489b3f7-c08a-b78e-e350-78c7c316780d.png)
3. 以下の通り設定する。
  - autopep8の有効化
    - editor.defaultFormatterを「ms-python:autopep8」。
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/19c2c237-2e20-0ccf-a413-093f365a320c.png)
    - python.formatting.providerを「None」。
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/9c72cc49-f0c9-81e4-1a8a-5489a004e651.png)
  - ファイル保存時の自動校正を有効にする
    - editor.formatOnSaveにチェックを入れる。
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/c189c927-dfac-e35f-c40e-ff9ff182a07f.png)

これで完了。

# 動作チェック

実際にやってみます。
視認性を上げるため、「indent-rainbow」で空白4つを可視化しています。
また保存前の赤い波線は「Flake8」で問題部分を表示している部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/fa0460c7-47cf-370c-e08e-d33b0072139e.png)

改行や空白などの過不足について、ファイルを保存する時にきちんと校正されていることが分かりました。

なお今回は特に取り上げては説明していませんが、「Flake8」はPEP8に沿っていない部分を可視化してくれるため、導入をおすすめします。
Pytorchでニューラルネットワーク入門しようとしたらロスが下がらなかった

# はじめに
WEBの記事を参考にニューラルネットワークに入門しようとしたら詰まり、検索ワードも分からずかなり時間を溶かしたので同じように迷う人のために記しておきます。
Qiita初投稿のため見づらいところあるかもしれませんがご容赦ください。

# 学習が進むにつれてロスが下が...らなかった
適当にググって出たページでサクッとニューラルネット入門しようとしたら全然ロスが下がらなかった。

``` python: 
for epoch in range(100):
  total_loss = 0
  for train_x, train_y in train_loader:
    output = model(train_x)
    loss = F.cross_entropy(output, train_y)
    model.zero_grad()
    loss.backward()
    optimizer.step()
    total_loss += loss.data
  if (epoch+1)%10 == 0:
    print(total_loss)
```
``` bash: 出力
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
```
？？？

学習後の重みを見ても...

``` python: 
print(model.fc1.weight.grad)
```
``` python: 出力
tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        # 長いので中略（途中も全部0）
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
```
ワーキレイダナー

# やろうとしていたこと
scikit-learnのwineのデータセットでワインの分類をしようとした。

``` python: データセット
from sklearn.datasets import load_wine
wine = load_wine()
```
``` python: モデル
class Net(nn.Module):
  def __init__(self):
    super(Net, self).__init__()
    self.fc1 = nn.Linear(13, 30)
    self.fc2 = nn.Linear(30, 2) # 本来のデータセットは3種類の分類だが2種類に絞った

  def forward(self, x):
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    return x
```

# 結論
**ReLUの使い方** が悪かったみたいです

どうやら**Dying ReLU**という現象があるようです。
重みが負の値に更新されたためにすべて0になりそれ以上逆伝播ができず重みの更新もできずという状態に陥っていたようです。
詳細は「Dying ReLU」でググると詳しい記事がいくつか出てくるのでそちらに丸投げします。（ごめんなさい）

**ReLU以外の活性化関数**を使うとかデータをあらかじめ**正規化**しておくとかすると解消しました。

# まとめ
ReLUって絶対正義ではなかったんだなって思いました。（そりゃそう）
あとデータの前処理重要ですね。

とりあえず無事入門できたのでガンガン勉強してきたいと思います。
[書籍レビュー] 実用Go言語

## 書籍概要
[実用Go言語](https://www.oreilly.co.jp/books/9784873119694/)

タイトルの通り実用的なGo言語の書き方について書かれた本です。
若干文章の結論が分かりづらい節がありましたがサンプルコード多めなので特に気にせずに読むことができました。
[A Tour of Go](https://go-tour-jp.appspot.com/welcome/1) や入門書でGoの言語機能を一通り使えるようになった後に読むのをおすすめします。

１〜６章まではGo言語についての基本と発展がまとまっているという感じで、７章以降はよりシステム開発チックな内容になっています。６章までは順に読みつつ７章以降は気になるトピックから読み進めるのが良さそうです。

## 本の目次

|章|内容|
|:-|:-|
|第１章|「Goらしさ」に触れる|
|第２章|定義型|
|第３章|構造体|
|第４章|インタフェース|
|第５章|エラーハンドリング|
|第６章|パッケージ、モジュール|
|第７章|Goプログラミングの環境を整備する|
|第８章|さまざまなデータフォーマット|
|第９章|Goとリレーショナルデータベース|
|第１０章|HTTPサーバー|
|第１１章|HTTPクライアント|
|第１２章|ログとオブザーバビリティ|
|第１３章|テスト|
|第１４章|クラウドとGo|
|第１５章|クラウドのストレージ|
|第１６章|エンタープライズなGoアプリケーションと並行処理|
|付録A|駆け足で学ぶGoの基礎|
|付録B|Goの最新情報を知るための情報源|


## 良かったところ

個人的にためになった内容を一部紹介します。

### 構造体とオブジェクト思考の違いを知る

オブジェクト指向の観点から見た構造体の用途が以下の４つに分けて紹介されています。

> ① ライブラリの機能を呼び出すメソッドを集約したインスタンス
> ② インターフェース経由で他から呼び出されるエントリーポイント
> ③ データセットを持ち運ぶためのバリューオブジェクト
> ④ タプルと呼ばれるようなデータの塊

自分の中で曖昧になっていた**Goの構造体では何ができて何ができないのか**を整理することができました。

### テンプレートメソッドパターンではなく、ストラテジーパターン
> Goではテンプレートメソッドパターンを使用しない代わりに、このようなパターン（ストラテジーパターン）を用います。

テンプレートメソッドパターンとはスーパークラスで処理の枠組みと主要なロジックを定義し、それを継承するサブクラスでロジックの一部をオーバーライドする設計のことです。
Goには継承もメソッドのオーバーライドもないため、このテンプレートメソッドパターンが利用できないので、この本では代わりにストラテジーパターンという一部の処理を引数で関数として渡せる設計が紹介されています。
公式パッケージの[net/http/httputil.ReverseProxy](https://pkg.go.dev/net/http/httputil#ReverseProxy)が具体例として紹介されていて実コードへの取り入れ方がイメージしやすかった点が良かったです。