OmniAICreator/Qiita-1.07M huggingface dataset:
要注意！？本当に怖いCloudFront

# はじめに
先日、海外向けに運用していた個人ブログがDDoS攻撃を受けてしまいました。
こういったサイバー攻撃は、企業に対して行われるものという先入観がありました。
しかし、調べてみると、最近では個人ブログも標的になってきていると報告があがっていました。
CloudFrontとS3で作成する静的サイトが人気になっており、特にCloudFrontの危険性について紹介したいと思います。

# DDoS攻撃って？
ざっくり説明すると、ウェブサイトやサーバーに対して過剰なアクセスやデータを送付するサイバー攻撃です。
インフラストラクチャーレイヤー攻撃(レイヤー3、4)とアプリケーションレイヤー攻撃(レイヤー6、7)の２つに分類されます。


ご指摘を頂きましたので、訂正いたします。
厳密には、EDoS攻撃でした。

# AWS Shield Standard
AWSを利用した場合、defaultでAWS Shield Standardが適応されます。
Standardでは、インフラストラクチャーレイヤー攻撃に対して自動的に防御してくれます。

# AWSでEDoS攻撃を受けた場合
CloudFrontとS3で構築された静的ブログを運営していると仮定して説明を行います。
インフラストラクチャーレイヤー攻撃に対しては、AWS Shield Standardが防御してくれます。
アプリケーションレイヤー攻撃に対しては、CloudFrontがオリジンサーバーへの到達を防いでくれるため、サーバーに影響が出ることはありません。
あれ？それじゃ大丈夫じゃないの？と思いますよね？
そこに大きな落とし穴があります。

# CloudFrontはキャッシュを返す
大量のアクセスが来た場合でも、キャッシュを返す事でサーバーの負荷を下げてくれますが、
悪意あるアクセスに対してもキャッシュを返す対応となってしまいます。
CloudFrontは従量課金のサービスです。
毎秒、数千件のアクセスがあった場合、データ転送量が膨大になってしまいます。
キャッシュサイズが1MBだったとして、毎秒数千倍、、、恐ろしすぎますよね。
そう、サーバーに対しての攻撃ではなくお財布を狙った攻撃になるのです。

# 対策方法
考えられる対策方法を並べます。
## AWS Shield Advanced
アプリケーションに対する攻撃に対しても防御してくれます。
攻撃によってCloudFront等の料金が大幅にアップした場合でも、Advancedに加入する事で返金対応が可能です。
ただし、月額3000USDのため、個人用途では高額になってしまいます。
## AWS Cost Explorer
料金を可視化して現在の料金を知ることは非常に大切です。
コスト異常のアラートを確認することで対策はできますが、根本的な対策にはならないので注意が必要です。
## AWS WAF
少し料金は掛かってしまいますが、おすすめの方法です。
同一のIPからの5分間のリクエスト数で、閾値を超えると以降はブロックなど、ルールを設定することができます。
Web ACL毎に5USD、ルール1つ毎に1USDの料金が掛かります。
同一のIPのリクエスト数と、特定の国からのアクセスを遮断などがおすすめのルールです。
## 番外:従量課金サービスを使わない
VercelやNetlifyなどの定額制のホスティングサービスを使用するのも、高額請求対策になります。
# さいごに
WordPressからの乗り換えで静的サイトを勧めているブログは多くあります。
中には、静的サイトはサーバーで動くものが無いからセキュリティ対策は不要などと書かれていたりします。
たしかに、今回紹介した内容は厳密にはセキュリティでは無いですか、、、
CloudFrontを使用する場合は、落とし穴がありますので注意が必要です。
安易に公開して放置しているのは、大変危険です。
皆さんも、この際にセキュリティを見直してみてはと思います。
【Rails】マイグレーションの変更内容の反映

# マイグレーションの状況の確認
db:migrateは、クエリを打ってデータベースを直接操作するようなことなく、migrationfileに記述された仕様の通りにデータベースのスキーマを設定できる処理のこと。
db:migrateが実行されると、migrationfileはそのバージョンに基づくIDにより管理されることになる。そのため、既存のmigrationfileの内容を変更して、再度db:migrateを実行しても、同じIDのmigrationfileによるマイグレーションが既に実行されている場合、変更内容は反映されない。

まず、現在のマイグレーションの状況を確認するため、以下を実行する。
```:terminal
$ rails db:migrate:status
```
すると例えば以下のようなマイグレーションの状況が出力される。
```
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20221016090215  Devise create users
   up     20221030072844  Add user id to users
```
ちなみにマイグレーションファイルの内容は以下のような感じになっている。

```ruby:20221016090215_devise_create_users.rb
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|

      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      t.datetime :remember_created_at

      t.timestamps null: false
    end

    add_index :users, :email
    add_index :users, :reset_password_token, unique: true
  end
end
```
```ruby:20221030072844_add_user_id_to_users
class AddUserIdToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :user_id, :string
    add_index :users, :user_id, eunique: true
  end
end
```
# マイグレーションのredo
マイグレーションをやり直すには```rails db:migrate:redo```を実行する。この処理は、マイグレーションのステータスを一度downにしてから、再度upにするもので、migrationfileの変更内容を反映させることができる。
（```rails db:rollback```を実行し、```rails db:migrate```を実行しても同様。）

その前に、二つに分かれているmigrationfileを一つにまとめておく。

```ruby:20221016090215_devise_create_users.rb
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|

      t.string :email,              null: false, default: ""
      t.string :user_id,             null: false
#今回は、user_idにnull:falseを付け加えることを変更点として、マイグレーションをredoする
      t.string :encrypted_password, null: false, default: ""

      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      t.datetime :remember_created_at

      t.timestamps null: false
    end

    add_index :users, :email
    add_index :users, :user_id, eunique: true
    add_index :users, :reset_password_token, unique: true
  end
end

```
もう一つのmigrationfileについては、以下のコマンドを実行して、downさせる。
```
$ rails deb:migrate:down VERSION=20221030072844
```
再度ステータスを見てdownになっていることを確認し、ファイルを削除しておく。
（downする前に削除すると、もう一度ファイルを作ってからdownさせ、削除するという手間が生じる。）
その上で、redoを実行する。
```:terminal
$ rails deb:migrate:redo
```
再度、マイグレーションの状況を確認すると、
```
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20221016090215  Devise create users
```
のように出力され、変更内容が反映される。
Error: Failed to initialize watch plugin "node_modules/jest-watch-typeahead/filename.js"の対処法【React】

# エラー内容
- コマンド
```sh:コマンド
npm test
```

- 実行例
```sh:実行例
>npm test

> react-tmp@0.1.0 test C:\Users\【ユーザ名】\Desktop\ReactTmpApp\react-tmp
> react-scripts test

Error: Failed to initialize watch plugin "node_modules/jest-watch-typeahead/filename.js":

  ● Test suite failed to run

    file:///C:/Users/【ユーザ名】/Desktop/ReactTmpApp/react-tmp/node_modules/jest-watch-typeahead/build/file_name_plugin/prompt.js:4
    import { PatternPrompt, printPatternCaret, printRestoredPatternCaret } from 'jest-watcher';
                            ^^^^^^^^^^^^^^^^^
    SyntaxError: Named export 'printPatternCaret' not found. The requested module 'jest-watcher' is a CommonJS module, which may not support all 
module.exports as named exports.
    CommonJS modules can always be imported via the default export, for example using:

    import pkg from 'jest-watcher';
    const { PatternPrompt, printPatternCaret, printRestoredPatternCaret } = pkg;

      at async requireOrImportModule (node_modules/jest-util/build/requireOrImportModule.js:65:32)
      at async watch (node_modules/@jest/core/build/watch.js:337:34)
      at async _run10000 (node_modules/@jest/core/build/cli/index.js:311:7)
      at async runCLI (node_modules/@jest/core/build/cli/index.js:173:3)

npm ERR! Test failed.  See above for more details.
```

# 解決策
以下コマンドを実行する

```sh:コマンド
npm i -D --exact jest-watch-typeahead@0.6.5
```

# 再実行
以下のようになれば成功

- コマンド
```sh:コマンド
npm test
```

- 実行例
```sh:実行例
>npm test

> react-tmp@0.1.0 test C:\Users\【ユーザ名】\Desktop\react-test\react-tmp
> react-scripts test
No tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.

Watch Usage
 › Press a to run all tests.
 › Press f to run only failed tests.
 › Press q to quit watch mode.
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press Enter to trigger a test run.
 PASS  src/App.test.js
  √ renders learn react link (28 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.068 s
Ran all test suites.
```

## 補足

```
No tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.

Watch Usage
 › Press a to run all tests.
 › Press f to run only failed tests.
 › Press q to quit watch mode.
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press Enter to trigger a test run.
```

- `a` : 全てのテストを実行
- `f` : 失敗したテストのみ実行
- `o` : 変更したファイルのテストのみ実行
- `q` : テストを終了する
- `p` : 正規表現でファイル名を絞ってテスト実行
- `t` : 正規表現でテスト名を絞ってテスト実行
- `Enter` : テスト実行
Retrofit2でログ出力

# はじめに
Retrofit2でデバッグ用にログ出力したかったので、使い方を自分用にメモ

## 参照元
https://futurestud.io/tutorials/retrofit-2-log-requests-and-responses

# 実装

## build.gradleに依存関係を追加

```build.gradle
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
```

## loggingをRetrofitに設定

Retrofitのインスタンス作成時にクライアントとして、loggerを設定したhttpClientを渡す

```
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BODY

val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor(logger)

val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(gsonFactory)
    .client(httpClient.build())
    .build()
```

# ログレベル
logger.levelで渡しているlevelには4種あり、出力の詳細さが変わる

## NONE
ログを出力しない

## BASIC
リクエストラインとレスポンスラインのみを出力

## HEADER
BASICのログに加えて
リクエストヘッダとレスポンスヘッダが出力される

## BODY
HEADERのログに加えて
リクエストボディとレスポンスボディが出力される
多言語FizzBuzzチャレンジ14日目:R

## これまでのまとめ
気がついたら、ようやく半分折り返したようです…。

https://qiita.com/tenteko/private/fc52f7aec63ba5f67854

https://qiita.com/tenteko/private/ca9813f0982370d0c901

https://qiita.com/tenteko/private/bc808ba59f6993019045

https://qiita.com/tenteko/private/74aa4c422196cb5cdeac

https://qiita.com/tenteko/private/ea22bd19360333f9ca85

https://qiita.com/tenteko/private/ec2f7c2f99229a55a7aa

https://qiita.com/tenteko/private/237556777f5c5546af6e

https://qiita.com/tenteko/private/264e4aca8a2ee6761a6c

https://qiita.com/tenteko/private/6e86fa0eeed9d24805ab

https://qiita.com/tenteko/private/f32baaf43fe0217b7fc7

https://qiita.com/tenteko/private/b44e1e5bfc91f6f3a52f

https://qiita.com/tenteko/private/333b9697c03561fb6158

https://qiita.com/tenteko/private/667f5f69eda60f221912

## 本日のお品書き
Rです。
統計によく用いますよね。
まったくFizzBuzzするものではないです。

## FizzBuzz
```R
for(i in 1:100){
    # なぜ%を重ねた
    if(i%%15==0){
        print("FizzBuzz")
    }else if(i%%3==0){
        print("Fizz")
    }else if(i%%5==0){
        print("Buzz")
    }else{
        print(i)
    }
}
```

## おまけ：ネットで見かけた面白い解法
- 上記コードはまったくRっぽくなくて、Rといえばベクトル演算みたいなところがありますよね。
- 下記リンク先にはそうした解法も含めて参考になるものがたくさんありました。(6)は特におもしろい。

https://uncorrelated.hatenablog.com/entry/20120218/1329564291
多言語FizzBuzzチャレンジ13日目:Julia

## これまでのまとめ
https://qiita.com/tenteko/private/fc52f7aec63ba5f67854

https://qiita.com/tenteko/private/ca9813f0982370d0c901

https://qiita.com/tenteko/private/bc808ba59f6993019045

https://qiita.com/tenteko/private/74aa4c422196cb5cdeac

https://qiita.com/tenteko/private/ea22bd19360333f9ca85

https://qiita.com/tenteko/private/ec2f7c2f99229a55a7aa

https://qiita.com/tenteko/private/237556777f5c5546af6e

https://qiita.com/tenteko/private/264e4aca8a2ee6761a6c

https://qiita.com/tenteko/private/6e86fa0eeed9d24805ab

https://qiita.com/tenteko/private/f32baaf43fe0217b7fc7

https://qiita.com/tenteko/private/b44e1e5bfc91f6f3a52f

https://qiita.com/tenteko/private/333b9697c03561fb6158

## 本日のお品書き
Juliaです。
Python絡みでJupyter Notebookを使っている時に、代替手段としてよく見かける名前ですね。

## FizzBuzz
```julia
for i in 1:100
    if i % 15 == 0
        println("FizzBuzz")
    elseif i % 3 == 0
        println("Fizz")
    elseif i % 5 == 0
        println("Buzz")
    else
        println(i)
    end
end
```

個人的な印象としては、かなりPythonに近い書きっぷりです（少なくともFizzBuzz程度のレベル感であれば）

## おまけ
ローカルにインストールしたくなかったのでDockerを使いました。`docker pull julia`で最新のイメージをゲット。`fizzbuzz.jl`として保存したスクリプトを実行すればOK。

https://mnru.github.io/julia-doc-ja-v1.0/manual/getting-started.html
多言語FizzBuzzチャレンジ12日目:Nim

## これまでのまとめ
https://qiita.com/tenteko/private/fc52f7aec63ba5f67854

https://qiita.com/tenteko/private/ca9813f0982370d0c901

https://qiita.com/tenteko/private/bc808ba59f6993019045

https://qiita.com/tenteko/private/74aa4c422196cb5cdeac

https://qiita.com/tenteko/private/ea22bd19360333f9ca85

https://qiita.com/tenteko/private/ec2f7c2f99229a55a7aa

https://qiita.com/tenteko/private/237556777f5c5546af6e

https://qiita.com/tenteko/private/264e4aca8a2ee6761a6c

https://qiita.com/tenteko/private/6e86fa0eeed9d24805ab

https://qiita.com/tenteko/private/f32baaf43fe0217b7fc7

https://qiita.com/tenteko/private/b44e1e5bfc91f6f3a52f

## 本日のお品書き
Nimさん。下記のような記事を読んで気にはなっていた存在。

https://zenn.dev/dumblepy/articles/b475b3b4f7d0da

## FizzBuzz

```nim
for i in 1..100:
  # 1..100はbuilt-inのcountup(1,100)と等価
  # 最後の要素を含めるのが少し感覚と合わない
  if i mod 15 == 0:
    # 人類は%かmodか統一すべき...
    
    # stringリテラルは厳密に" "
    echo "FizzBuzz"
  elif i mod 3 == 0:
    echo "Fizz"
  elif i mod 5 == 0:
    echo "Buzz"
  else:
    echo i
```

## おまけ
今回も環境構築はスキップ。オンライン実行環境があると手をつけやすくて良いですね。(ちとコンパイルは遅かったけど）

https://play.nim-lang.org
多言語FizzBuzzチャレンジ11日目:Ruby

## ここまでのまとめ
https://qiita.com/tenteko/private/fc52f7aec63ba5f67854

https://qiita.com/tenteko/private/ca9813f0982370d0c901

https://qiita.com/tenteko/private/bc808ba59f6993019045

https://qiita.com/tenteko/private/74aa4c422196cb5cdeac

https://qiita.com/tenteko/private/ea22bd19360333f9ca85

https://qiita.com/tenteko/private/ec2f7c2f99229a55a7aa

https://qiita.com/tenteko/private/237556777f5c5546af6e

https://qiita.com/tenteko/private/264e4aca8a2ee6761a6c

https://qiita.com/tenteko/private/6e86fa0eeed9d24805ab

https://qiita.com/tenteko/private/f32baaf43fe0217b7fc7

## 本日のお品書き
RailsじゃないよRubyだよ。大学の頃に必修の授業で触ったきりですね。

## FizzBuzz
```ruby
for n in 1...101 do
  if n%15==0
    puts 'FizzBuzz'
    # 人類はいい加減else if, elseif, elifを統一すべき。elsif...
  elsif n%3==0
    puts 'Fizz'
  elsif n%5==0
    puts 'Buzz'
  else
    puts n
  end
end
```

## おまけ：実行環境
環境構築したくなかったので今回はオンラインのプレイグラウンドを使いました。

https://try.ruby-lang.org
[Git] リポジトリに個人メモ・シェルを残す

# はじめに

そもそも情報は共有しろというのは自明であるが､開発を行っているとドキュメント化したりGit管理したりするほどでもないメモやスクリプトが発生する｡いつものメモ帳に記しておくことも可能だが､Git管理下のディレクトリにあった方が都合がいいケースもある｡そんなケースに対応する私が採用している方法を紹介する｡

# .git/info/exclude に書く

ご存知の方も多いと思うが、Gitには `.gitignore` とは別にローカルリポジトリごとに除外パターンを設定する機能がある。 `.git/info/exclude` である。 `.git/info/exclude` を以下、例のように書くことで、一時的に発生するメモやスクリプトに対応している。

```:.git/info/exclude
_*.sh
_*.md
_*.txt
_*.log
```

例では `_debug.sh` や `_memo.txt` のようなファイル名は除外される。ドキュメントやスクリプト管理、延いては開発ルールにまでまたがる微妙な内容ではあるが、環境やリポジトリに合わせて適宜変更して活用してもらえると嬉しい。
2022/11/07主にITとかセキュリティの記事

ネクストフロンティアはどこ？WEB3.0、Defiとは？(11/4)
https://zuuonline.com/channels/bank-daiwa/242333

渡辺創太氏のアスターがNTTドコモと提携、マスク氏のツイートから生まれた暗号資産【10/29～11/4のトップニュース】
https://www.coindeskjapan.com/164745/

「サイバー犯罪」に関する相談増加 滋賀県警が注意呼びかけ(11/4)
https://www3.nhk.or.jp/lnews/otsu/20221104/2060011909.html

ランサムウェアは「必要悪」？ 分業・専業で“サブスク化”も(11/5)
https://news.yahoo.co.jp/articles/ec698ef59258ea7e60cc592c047df6009fcf37d2

日本はサイバー攻撃に対してあまりに無能…ここまで後れを取った決定的な理由(11/5)
https://news.yahoo.co.jp/articles/6bb5afa18bc024ea91dec3a37f05fe3a87517016

仮想通貨のステーブルコインとは？種類や今後について解説(11/5)
https://crypto-times.jp/what-is-stablecoin/

人気のITインフラ監視ツールのOSS版に複数の脆弱性見つかる(11/5)
https://news.mynavi.jp/techplus/article/20221105-2503785/
Node.jsをアップデートできない問題を解決した (Apple M1)

## 背景
firebaseをインストールしたのですが、Node.jsのバージョンが古くて「Incompatibleだよ」と言われました。
そのためNode.jsをアップデートしようとしたのですが、つまづいてしまったので、解決した方法をこの記事に書くことにしました。

## 症状
Firebaseコマンドを利用しようとしたらターミナルがこのように表示してきました。
```
Firebase CLI v11.16.0 is incompatible with Node.js v12.19.0 Please upgrade Node.js to version ^14.18.0 || >=16.4.0
```
どうやらNode.jsのバージョンを16.4.0以上にアップグレードしなければいけないようです。

HomebrewおよびNodebrewをインストールしており、Nodebrewを利用してNode.jsのアップデートを試行しました。

### Node.jsアップグレード失敗。"Darwin arm64 is not supported"
nodebrewでnode.jsをアップグレードを試しましたが、失敗し以下のエラーを吐きました。
```
Darwin arm64 is not supported
```
こうなる理由は、私のNodebrewのバージョン(v1.0.1)では、「arm64」、つまりApple M1はサポートされていないためのようです。

そのため、Node.jsの前に、まずNodebrewのアップデートが必要になりました。
まずは「Nodebrewのアップデート」、次に「Node.jsのアップグレード」の手順を紹介します。

## 解決

### Homebrewをアップデート
一応Homebrewもアップデートしておきます。Homebrewのアップデートのコマンドは以下の通りです。
```
brew update
```


### nodebrewアップデート
nodebrewのアップデートを以下のコマンドで実行します。
```
brew install nodebrew
```

しかし、、、成功しているようなのですが、以下のコマンドでバージョンを確認すると、
```
nodebrew -v
//結果: nodebrew 1.0.1
```
なんと、、、全く変わっていません。
（実際には、アップデートは出来ていました）

#### パスを通す
上記のようにバージョンが変わっていないように見えたのは、以下のパスを通していないためでした。
```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```
このパスをディレクトリの .zshrc か .bashrc に記入する必要があります。

.zshrc か .bashrcか、についてですが、
自分のMacのデフォルトのシェルを調べるコマンドがあります。以下のコマンドを実行します。
```
echo $SHELL
```
私の場合はこれで .zshrc だというのが判明しました。
そのため、.zshrc にパスを記入することにします。

#### パスの通し方
以下のコマンドを実行し、進めました。
```
//ホームディレクトリに移動
cd ~/

// ディレクトリ内のファイルを一覧表示（.zshrcなどは隠しファイルのためこのコマンドが必要
ls -a

// 設定ファイルがない場合にはこれで作成(.zshrcの場合)
touch .zshrc

// .zshrcを開く
open ~/.zshrc
```
これで設定ファイル(.zshrc)が開けます。
テキストエディットで開けるはずなので、そこに以下のパスを記入します。
```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

その後、ターミナルでパス変更を反映させます。
```
source ~/.zshrc
```

これでパスが通りました。
改めてnodebrewのバージョンを再確認します。
```
nodebrew -v
//結果: nodebrew 1.1.0
```
これでNodebrewのアップデートがついに成功しました。


## Node.jsのアップグレード
Nodebrewが正しくアップデートできたので、次はNode.jsです。以下のコマンドで最新の安定版がインストールできます。
```
nodebrew install-binary stable
```
バージョン確認のため、以下のコマンドを叩きます
```
node -v
//結果: v18.12.1
```
Node.jsのアップグレードが成功したことが分かりました。これでOKです。

※これでもバージョンが変わらないようであれば、以下のコマンドを利用してください。バージョンを指定できます。
```
nodebrew use 18.12.1
// バージョンはインストールしたものを入力してください
```

ちなみに、これによりFirebaseのエラーは突破したのですが、別のエラー（digital envelope routines::unsupported）が発生しましたが、これは以下の記事の内容で解決しました。

https://zenn.dev/yoonchulkoh/articles/1d15251ec0b3bf


## 参考になったページ
ありがとうございました。

https://programmer-life.work/diary/nodebrew-install-binary-stable-error-darwin-arm64-is-not-supported-update-nodebrew

https://qiita.com/arimuuuura/items/95e489a835d7bf31a4a5

https://amateur-engineer.com/mac-path-zsh/

https://parashuto.com/rriver/tools/homebrew-most-used-commands
【PHP】Laravelの`bearerToken()`メソッドを使ってリクエストヘッダーのBearerトークンを取得

## 概要
LaravelでAPIを開発するときなど、認証時にリクエストヘッダーのトークンを使うことがあると思います。[【Laravel8.x】リクエストヘッダーの値を取得する。](https://yama-weblog.com/get-request-header-data-in-laravel8/)の記事にある通り、requestからヘッダー値を取得する方法でも全然良いと思うのですが、Laravelでは`bearerToken()`というメソッドが用意されていたので紹介します。

## bearerToken()メソッドについて
[How to get Bearer token from a request in Laravel](https://stackoverflow.com/questions/47158522/how-to-get-bearer-token-from-a-request-in-laravel)のstackoverflowの記事に使い方など書かれています。基本的にはrequestのオブジェクトにメソッドが用意されているので、`$token = $request->bearerToken();`のような形で取得できます。

## 実装サンプル
おそらくリクエストヘッダーのトークンを確認するのは、Middlewareで実装するケースが多いと思うので、Middlewareでの実装サンプルを紹介します。

```php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

use App\Services\UserAccount\UserAccountService;

class AuthenticateToken
{
    // token複合化用のサービスの定義（実装は記載割愛）
    private $userAccountService;
    public function __construct(
        UserAccountService $userAccountService,
    ) {
        $this->userAccountService = $userAccountService;
    }

    public function handle(Request $request, Closure $next)
    {
        // Bearerトークンを取得
        $authToken = $request->bearerToken();

        if (isset($authToken)) {
            // authTokenを複合化&userのidを取得（実装は記載割愛）
            $id = $this->userAccountService->decodeUserIdToken($authToken);
            // Controllerに渡すリクエストにマージ
            $request->merge(['userAccountId' => $id]);
            return $next($request);
        }
        // トークン内容が取得できなかったらエラーを返す
        return response()->json(
            [
                'message' =>  'Can not authorize token'
            ],
            Response::HTTP_UNAUTHORIZED
        );
    }
}
```
その状態管理はトップダウン型(Zustand的)？ボトムアップ型(Jotai的)？Reactのディレクトリ構成と共に考える short ver.

本格的に記事にするのはまだ時間がかかりそうなので、ショートバージョンでたまにはこちらに。

Jotaiを推して入るものの、ずっとディレクトリ構成に悩んで答えを出せずに居た所とある記事が目に止まりました。

その記事のおかげでどう考えるべきか踏ん切りがついたのでそれをツイートでまとめてみました。↓

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">これを見て自分の中の靄が晴れてきた感じ。<br>Jotai / Recoil は従来のReduxのようなトップダウンな状態管理ライブラリではなくボトムアップ型。<br>なので一元的にまとめるような構成は哲学に反してる気がする。<br>Single source of truth 、巨大なstoreから切り出すのを忘れよう？<a href="https://t.co/Vox3BW7rlf">https://t.co/Vox3BW7rlf</a> <a href="https://t.co/qn0O8FF4Pt">pic.twitter.com/qn0O8FF4Pt</a></p>&mdash; Teruhisa Yamamoto (@tell_y_t) <a href="https://twitter.com/tell_y_t/status/1589082944072978432?ref_src=twsrc%5Etfw">November 6, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

トップダウン型であるReduxやZustandならば元記事のように1箇所に集めるパターンは理にかなっていると思います。
今回はボトムアップ型である状態管理ライブラリはどうするべきなんだろう、という視点での考察でした。

### 余談
この記事を書いて寝ようと思っていたところに Jotai 作者の @daishi さんがこんなツイートを。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Zustand is primarily designed for single store, but multiple stores are possible too. I have suggested only isolated store use case because you can&#39;t coordinate them.<br><br>Jotai and Valtio have &quot;derive&quot; capability.<br><br>Can we do similar? Here&#39;s derive-zustand:<a href="https://t.co/3weQUKWbXj">https://t.co/3weQUKWbXj</a></p>&mdash; Daishi Kato (@dai_shi) <a href="https://twitter.com/dai_shi/status/1589279106201718785?ref_src=twsrc%5Etfw">November 6, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ZustandでJotaiのように派生storeを簡単に作れるようにしちゃったもんで横槍を強めに入れられた感じでした。楽しいですね？
（Zustandがボトムアップ型のアプローチでコーディングできるようになったのでせっかく引き合いに出してたのに説明が面倒になったしもう笑うしか無くてあぁ楽しいな、って感じです）
デシジョンテーブルについて

# まえがき
今回は職場の勉強会でデシジョンテーブルについて学ぶ機会があったので、まとめてみようと思います。
何か間違っていることなどありましたらご教授ください！
## デシジョンテーブルとは
デシジョンテーブル（決定表）とは、対象が取り得る条件（入力）と、その結果の動作（出力）を洗い出した上で整理し、マトリクス上に一覧化した表のことです。
ということですが簡単に言えば
- 対象についての条件とその結果を表にまとめ見やすくしたもの？

といったところですかね？
まあよくわからないので実際の例を見てみましょう！
## 具体例①
実際に勉強会の時に使った例が２つあるのでそれぞれ見ていきましょう！
![スクリーンショット 2022-11-07 0.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/57a33012-1e06-d131-2adf-6fd4ed0ee297.png)
↑が実際のデシジョンテーブルです
![スクリーンショット 2022-11-07 0.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/d7a664d6-97f3-edd0-9459-5449e3a4f4e4.png)
↑がこのお店の割引の条件です
このデシジョンテーブルではピザ屋の宅配時のクーポン利用などに関する条件を表にまとめています
１列目２行から４行までに注文の条件、５行から８行までに結果が置かれています
どの条件でどの割引が適応されるのかが見やすく表示されていますね
例えば「お会計1500円以上」「店頭受け取り」「クーポン無し」の時の割引を知りたければ４番の列を見てあげれば、「ポテトサービス」「２枚目無料サービス」が受けられるということがわかります
## 具体例②
二つ目の例です！
![スクリーンショット 2022-11-07 0.31.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/684ace56-5d59-890d-4ad7-428468c035f5.png)
↑デシジョンテーブル
![スクリーンショット 2022-11-07 0.31.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/3415ba89-c926-b296-33df-8023c4d546b1.png)
↑条件
この例は配送業者の配送料に関するデシジョンテーブルです
条件がいろいろ書いてありますがまとめると「プレミア会員」「5000円以上の購入」「お急ぎ便」の３つです
それぞれのyes/noの条件で配送料がいくらなのか見ることができますね
## 注意点
勉強会では条件からデシジョンテーブルを作るということをしました
その時に注意するべき点があるなぁと思ったので自分なりの理解を共有させていただきます！
- 簡易化
- 列数

についてですね
- まず「簡易化」についてです
![スクリーンショット 2022-11-07 0.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/7b9f7609-8d4a-d162-c051-b09e84b330f0.png)
具体例①のピザの宅配のデシジョンテーブルですがこちらは簡易化することができます。
具体例①では条件の中に「宅配の場合でクーポンがあれば20%OFF」とありますね
ですので「受取方法」の行が「店頭」の場合はクーポンのあり/なしを判定する必要はないので下記のデシジョンテーブルがより簡易的なものになります
![スクリーンショット 2022-11-07 0.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/0ad436ca-28b9-d80b-cc10-a61b67bcc69e.png)
- ２つ目が「列数」についてです
デシジョンテーブルを作成する時に条件の数と結果の数はすぐにわかりますが、判定の結果が何パターンになるのかが自分にはすぐ判断できませんでした
勉強会でわかりやすく説明していた人がいたので共有しておきますと
__条件の分岐数を掛け合わせていけばいい__
ということでした
![スクリーンショット 2022-11-07 1.05.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/321a5078-4c1b-f890-31b2-1a4b63b29732.png)
一つ例を挙げて説明してみます
これはプリペイドカードの「会員のレベル」「チャージ額」「チャージ時の抽選」に関するデシジョンテーブルですが、ランクが３種類、チャージ額が３種類、抽選結果が２種類のデシジョンテーブルなので
3x3x2=18通りのパターンになる、ということですね
※このデシジョンテーブルも抽選に下記の条件があると「簡易化」できますね！
![スクリーンショット 2022-11-07 1.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2901058/38aa90b3-07f6-7d66-abd3-68013a9292e7.png)
## あとがき
この記事は勉強会に参加できなかった方のために書いてみましたが、人に説明することを考えて書くとすごく身になっている気がしますね。また機会があれば書こうと思います！
何か間違っている点、説明不足な点、わかりにくい点などあれば是非教えてください！
## 参考文献
書籍「ソフトウェアテスト技法練習帳 -知識を経験に変える40問-」著：梅津正洋、他
Webサイトhttps://shiftasia.com/ja/column/%E3%83%87%E3%82%B7%E3%82%B8%E3%83%A7%E3%83%B3%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%EF%BC%88%E6%B1%BA%E5%AE%9A%E8%A1%A8%EF%BC%89%E3%81%A8%E3%81%AF/
[Rails]URLの先頭にhttp://をつけるカスタムバリデーション



## やりたいこと

最近バックエンド側の開発では適切なバリデーションをかけることがとても重要なことがわかりました。
今回は規格以外のデータを保存できないようにするバリデーションに加えて、
データが規格以外だったらデータを規格に合うように修正して保存するバリデーションの作成の簡単に紹介したいと思います。

## 不具合事例
今回の案件としては、お客さんの入力した外部URLの先頭に`http://`及び`https://`がついてない場合、link_toメソッドだと、サービス内のPathになってしまいます。
わかりやすくローカル環境の例で説明します。

`localhost:3000/posts`ページで`link_to "yahoo", "www.yahoo.com"`にすると
`yahooのサイト`ではなく`localhost:3000/posts/www.yahoo.com`に飛びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2350392/3f839508-b92d-dbdf-4412-0b13df792130.png)

`link_to "yahoo", "https://www.yahoo.com"`にすると、狙い通り、`yahooのサイト`に飛びます。

## 解決方法
これを解決するために,保存しようとしているURLの先頭に`http://`や`https://`がついているかを確認し、
ついてなかったら付けて保存する必要がありますね。

下記のように`model/user.rb`にメソッドを定義して`vaildate`に`メソッド名`を入力することで、`vaildate`として使うことができます。

```rb
class User < ApplicationRecord

  validate :url_check

  def url_check
    url = self.url
    if url
      unless url.blank?
        unless url.split(':')[0] == 'http' || url.split(':')[0] == 'https'
          url = "http://" + url
        end
      end
    end
  end
```
とても簡単ですが、以上になります。
Microsoftストア用のW-8BENの作成

Microsoftストアにてアプリを一部有料で公開していますが、MicrosoftからTax Profileが期限切れになるので更新するようメールが来て、W-8BENを作成したので、その覚書です。

以前にTax Profileを登録したときには、必要項目は埋めたものの、W-8BENを明示的に作成した記憶はなかったので、一つ一つ調べながら進めることになり、とても時間がかかりました。ストアのアプリのケースについてはろくに情報がないんですよね。

## 概要

先にW-8BENについて書いておきます。

- ストアの収益は米国を経由するので、そのままでは米国の国内歳入庁（IRS: Internal Revenue Service）により30%の源泉徴収を取られる。
- 日本は米国と租税条約（二重課税を回避するための条約）を結んでいるので、IRSが定める所定の書類を提出すれば、米国の源泉徴収は0になる。
- このための書類は米国との関係によって変わってくるが、一番シンプルなケース（日本人で、日本在住で、個人で、米国でビジネスをしていない）ではW-8BENとなる。
- この書類はストアに提出しておけばよいので、IRSと直接やり取りするわけではない。提出はストアのウェブ上で入力すればよい、というか要求される。
- 完全な定型書類で、証拠書類を用意する必要もないので、やり方が分かれば難しくはない。

## 具体的な方法

Microsoft Partner Centerからのメールに入力画面への入り方が書いてあります（xxxxxxxxは自分のSeller ID）。

> Dear Partner,
> You are receiving this email because the tax profile for your company with seller id xxxxxxxx needs to be updated and requires your action. Sign into Partner Center and update the profile so that you'll be able to receive payouts from Microsoft. To update your profiles: 
>
> 1. Sign into Partner Center with your Azure AD tenant credentials.
> 2. If you get the option to select from __Work__ or __Personal account__, pick __Work account__.
> 3. Select the gear icon on the right side of the screen to open the __Settings__ menu, and then select __Account settings__.
> 4. Select __Payout and tax__ and then select __Payout and tax profiles__.
> 5. Select the __Tax profiles__ section on the page.
> 6. Look for seller id xxxxxxxx and update the profile as required.
> 7. For more information on updating payment and tax profiles, refer to the [Create and manage payout and tax profiles](https://docs.microsoft.com/en-us/partner-center/incentives-create-and-manage-your-payout-and-tax-profiles). 
>
> Thanks, Microsoft

この指示のとおり、__Tax Profiles__ を選んで右端のEditをクリックすると入力が始まります。

1. 米国との関係の選択肢があるので、米国人でなく、米国と特に関係もない、個人を選択して進む。
1. __Tax status__ で __Tax ID Type__ という項目があるが、ここはSelectのまま進む。
1. __Tax form__ まで来たら、__Launch tax form__ をクリックすると、W-8BENの作成フォームが開く。
1. 電子署名に関する同意にチェックを入れて進む。
1. 氏名を入力。
1. また米国との関係の選択肢があるので、同じように選択。
1. __Income Type__ という項目があるが、これは __Other Copyright Royalities__ と __Independent Personal Services__ が自動チェックされていて変更できない。そのまま進む。
1. __Permanent Address__ はJAPANを選択すると、先に入力していた住所が自動入力される。 __Mailing Address__ は同じ住所であればスキップ。
1. 外国の税番号（TIN）の項目があるが、ここは確たる回答はないが、マイナンバーを入れればいいらしい。
1. 生年月日を入力。
1. 租税条約の項目があるので、JAPANを選択する。規定のある条を指定する選択があるが、自動的に12(1)だけが選択可能になるので、それを選択。__Rate of withholding__ （源泉徴収税率）は30%と0%の選択があるが、これは適用してほしい税率なので0%を選択。
1. 最後に入力内容を確認して進むと、これまでの情報が入力されたW-8BENが生成される。これはPDFをダウンロードして保存可。
1. 元の画面でStatusがPending Microsoft validationになる。
1. しばらくするとStatusがCompleteになり、完了。

生成されたPDFから個人情報を除いたものを参考までに貼っておきます。
![w-8ben-store-cleaned.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60028/b8262196-7142-8ef0-fe69-1bcc7ceb8b4c.png)
今まで考えたことなかったですが、ストアの収益って種別はロイヤリティなんですね。
GitHub Actions の workflow name を動的に適用する


## はじめに

2022/09 から GitHub Actions の worklflow name が動的に定義可能になりました。
これまでは、コミットメッセージなどの決められたテキストが表示されていましたが、workflow の実行時に個別定義することが出来るようになりました。

## workflow name を動的に適用する

workflow name を動的に適用するためには、 YAML 内に `run-name` を定義します

```yaml:.github/workflows/test.yml
name: Test
run-name: Test run-name here!
```

run-name 内では `${{ github }}` や `${{ inputs }}` の context のみが利用出来ます

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#run-name

### 利用例

例として以下のような、 main branch に push されたら shell を実行する workflow が定義されていたとします

```yml:.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v3
      - run: sh deploy.sh
```

多くの場合 default branch (main/master branch) に 直接 push せず merge されることが多く、標準設定のままのコミットメッセージだと "Merge pull request #XX from foo/bar" が一覧に表示されるだけになってしまいます。
今回の例では、 deploy されたと言うことを表示させてあげれば良いと考えられるため以下のように定義するとよいでしょう。

```yml:.github/workflows/deploy.yml
name: Deploy
run-name: Deploy to XXXX

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v3
      - run: sh deploy.sh
```

記載した例には、workflow name が動的に定義出来るようになったメリットを享受出来ていませんが、^ にも記載しているとおり、 `${{ github }}` や `${{ inputs }}` の context が利用出来るため自身により最適なメッセー定義を考えてみると面白そうです

## 最後に

`run-name` を適切に設定してあげることで迷うこと無く CI/CD の実行やその結果を確認すると言ったことが出来るようになります
小さなことかも知れませんが、開き間違いなどのストレスなく開発出来る環境にしていきたいですね。

## Reference

GitHub Actions: Dynamic names for workflow runs

https://github.blog/changelog/2022-09-26-github-actions-dynamic-names-for-workflow-runs/

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#name
VBAスタンダード WorksheetFunctionまとめてみた

# VBAスタンダードのによく出る関数
## 1. Sum関数

範囲内の数値の合計
```
=WorksheetFunction.Sum(範囲,列)
```

## 2. SumIF関数

条件を満たすすべての数値の合計
```
.SumIf(条件の範囲,条件,足す範囲)
```
## 3. CountIf関数

条件を満たすセルをカウント
```
.CountIf(範囲,条件)
```
## 4. Large関数

n番目に大きい値を取得
```
.Large(範囲,n)
```
## 5. Small関数

n番目に小さい値を取得
```
.Small(範囲,n)
```
## 6. EoMonth関数
開始日からnヶ月後の最終日を取得
```
.EoMonth(開始日,n)
```
## 7.VLookup関数
表の縦方向にデータを検索し、一致した値と同じ行にあるデータを取得
```
.VLookup(検索値,範囲,列番号,検索方法)
```
`列番号` 
左から数えて何列目か(1番左の列は1)
`検索方法` 
FALSE→全く同じ値
TRUE&nbsp;→1番近い値
## 8. Index関数
行番号と列番号に基づいて、リストやテーブルからセル値を取得
```
.Index(範囲,行番号,列番号)
```
## 9. Match関数
検索した値のセルの場所を取得
```
.Match(検索値,範囲,方法)
```
`方法`
-1→検索値以上の最大値
0&nbsp;→検索値に完全一致
1&nbsp;→検索値以下の最小値


## 10. SubTotal関数
さまざまな集計値を取得する関数
```
.SubTotal(方法,範囲)
```

|方法|意味  |同等の関数|
|---|---|---|
|1  |平均値  　　　　　　|AVERAGE |
|2  |数値の個数  |COUNT  |
|3  |データの個数  |COUNTA  |
|4  |最大値      |MAX  |
|5  |最小値      |MIN|
|6  |積         |PRODUCT     |
|7  |普遍標準偏差  |STDEV.S  |
|8  |標本標準偏差  |STDEV.P  |
|9  |和  |SUM  |
|10  |不偏分散  |VAR.S |
|11  |標準分散  |VAR.P  |

# 最後に
以上です。不明点や間違っている点があればコメントでお知らせください。
Next.jsアプリをDocker DesktopのKubenetes上にデプロイ

Next.jsアプリケーションをDocker DesktopのKubernetes上にデプロイしました。

# 前提条件
- Mac(Big Sur v:11.6.5)
- Kubenetes on Docker desktop を有効化済み
- kubectl, yarn等の必要ツールをインストール済み

# ゴール
Next.js アプリケーションをDocker desktopのKubernetesにデプロイします。
ゴールはこのようになると思います。
![nextjs-k8s1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649199/88117753-da2d-e5d3-2451-57912d539752.jpeg)

# 手順
## デプロイするNext.jsのセットアップ
yarnで実行しました。
```zsh
> yarn create next-app --example with-docker nextjs-k8s-app
# Ref: https://github.com/vercel/next.js/issues/33493
# Ref: https://nextjs.org/docs/deployment#docker-image
# Ref: https://github.com/vercel/next.js/tree/canary/examples/with-docker
```

Docker Imageをbuildし、DockerHubに登録します。
DOCKER_HUB_USER_IDは各自自分のDockerHubに置き換えてください。
```zsh
> cd nextjs-k8s-app
> docker login # Optional
> docker build -t DOCKER_HUB_USER_ID/nextjs-k8s-app . && docker push DOCKER_HUB_USER_ID/nextjs-k8s-app
```
## Kubenetesの準備
docker desktopにcontextを変更します。
```zsh
> kubectl config use-context docker-desktop
# Ref: https://docs.docker.com/desktop/kubernetes/#use-the-kubectl-command
```
Namespaceを作成します。
```zsh
> kubectl create namespace nextjs-k8s
```

## deployment.yamlの準備
deploymentリソースのmanifestファイルを作ります。
どこでもいいですが、今回はデプロイするNext.jsアプリのrootに作ります。
```yaml: deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextjs-k8s-app-deployment
  labels:
    app: nextjs-k8s-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextjs-k8s-app
  template:
    metadata:
      labels:
        app: nextjs-k8s-app
    spec:
      containers:
      - name: giraffe-app
        image: DOCKER_HUB_USER_ID/nextjs-k8s-app # DOCKER_HUB_USER_ID will be replaced.
        ports:
        - containerPort: 3000
# Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
```
deploymentリソースをnextjs-k8s(Namespace)に作成します。
```zsh
> kubectl apply -f deployment.yaml -n nextjs-k8s
```
deploymentリソースができているか確認します。
```zsh
❯ kubectl get deploy -n nextjs-k8s
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
nextjs-k8s-app-deployment   1/1     1            1           10s
```
## Serviceを作成し、外部からアクセス可能にする
正常に動いていそうですが、このままではCluster外部からアクセスできないため、serviceリソースを作成し公開します。
```zsh
❯ kubectl expose deployment -n nextjs-k8s nextjs-k8s-app-deployment --type NodePort --port 80 --target-port 3000
```
serviceリソースができているか確認します。Node portは自動的に割り振られます。
```zsh
❯ kubectl get service -n nextjs-k8s
NAME                        TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nextjs-k8s-app-deployment   NodePort   10.101.111.217   <none>        80:30812/TCP   10s
```
## ブラウザからアクセスする
今回はNode portとして30812が割り振られているので以下のURLにアクセスしてみます。
```zsh
http://localhost:30812
```
無事表示されています。
![Screen Shot 2022-11-06 at 23.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649199/d420eb2f-26c0-638c-c2d1-598d5f211fb1.png)

## クリーンナップ
最後に作ったリソースを消して終了です。
```zsh
> kubectl delete namespace nextjs-k8s
> docker rmi DOCKER_HUB_USER_ID/nextjs-k8s-app
```

# まとめ
無事デプロイできたようです。
今回は非常にシンプルな構成にしたので今度はIngressなどを作ったりネットワークポリシーの設定をしたりしてみたいです。
無料プランpowerappsでQRコードのPDFを作成してダウンロードできるか検証してみた。

スマホアプリでpdfをダウンロードさせたくて四苦八苦したのでメモとして残します。
結論から言うと出来ませんでした。

## Print関数で印刷する。
ブラウザの機能で印刷を呼び出しているだけのようなのでスマホだと機能しません(残念
QRコードの作成自体は、サービスを使います。
https://goqr.me/api/

## Power Automateを使いPDFを作成する
onedrive for businessのコネクタにファイルを変換するというものがあります。
htmlからjpgやpdfに変換したりできるみたいです。
ただ、そのままhtmlデータからpdfに変換しようとした際に、日本語が入っているとエラーが出て変換出来ないようでした...
(英語のみだとそのまま変換される)

なので一度jpgに変換してからjpgをワードに埋め込んでワードをpdfに変換するという方法が紹介されていたので試そうとしましたが、ワードが有料コネクタだったので使えませんでした。
(エクセルは無料でできるのに...)
あとhtmlをjpgに変換するとサイズが大きければ縮小されるようですので汎用的な使い方は出来ないと思います。

※参考
https://stackoverflow.com/questions/56990210/how-to-print-bar-code-from-microsoft-powerapp



## TCPDFを使ってPDFを作成する。(解決)

ダウンロード自体はappsの関数にdownload関数があってそれを使えばできそうなのですが、sslのサイトではないとdownload関数が使えないようです。
ただ、Automateを使ってonedriveに一度保存してからonedriveのurlをdownload関数に渡せばそのままダウンロードできると思ったのですが、apps側で一度でも共有リンクを開いていないとオリジナルのファイルはダウンロードできないようです。
なので諦めて、Launch関数という指定のurlをブラウザで開く関数でonedriveの共有リンクを開く形にしました。
(スマートではないですが...)

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-download

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-param

## その他
base64にファイルを変換してダウンロードさせる等も考えましたが、変換まではAutomateのonedriveファイルコンテンツの取得で変換出来ますが、ダウンロードが出来ませんでした。
pdfviewerコントロールではbase64を使ってPDFの表示はできるみたいです。
【TypeScript】ユーザー定義型ガード（user-defined type guard）が必要な状況について

## ユーザー定義型ガードが必要な状況とは？

以下のコードは一見すると、そのまま使えそうだが、「TS2339: プロパティ`toUpperCase`は型`number`に存在しません。」となりコンパイルできない。
```TypeScript
function isString(a: unknown): boolean {
  return typeof a === 'string'
}

function parseInput(input: string | number) {
  let fomattedInput: string
  if (isString(input)) {
    fomattedInput = input.toUpperCase(); // string型と解釈されずにエラーとなる
  }
}
```
`isString`の中で`typeof`を使って型の絞りこみが行われているものの、呼び出し元である関数`parseInput`のスコープには引き継がれずにコンパイラではただ`isString`が`boolean`を返しているということぐらいしか解釈できないらしい。`input`が`string`として解釈されないために`toUpperCase`は使えない。この状況を回避するには`ユーザー定義型ガード`を使って`isString`に渡された引数が`string`であることを型チェッカーに伝えてやる必要がある。

```TypeScript
function isString(a: unknown): a is string {
  return typeof a === 'string'
}

function parseInput(input: string | number) {
  let fomattedInput: string
  if (isString(input)) {
    fomattedInput = input.toUpperCase()
  }
}
```

## 参考・引用
「プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発」
ISBN-10 ‏ : ‎ 4873119049
ISBN-13 ‏ : ‎ 978-4873119045
【eclipse】Springスタータープロジェクトの名前をリファクタリング(変更)した際に出現するエラーの解消方法

## 前置き
プロジェクト名を変更しようと、以下キャプチャから修正したところ
多数のファイルで見慣れないコンパイルエラーが出現。
ググっても中々解決策を見つけられず意外と手こずったので、もし同じような事象で
困っている方がいたら、解決手段の一つとして参考にしていただけたらと思います。
![20221106-223259.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/dd9f8921-7cb1-e77a-06f2-e01fa5d7c527.png)

## 結論
自動生成されるsettings.gradleファイルの内容を修正する事で解決できる。
![20221106-233406.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/d966f8eb-ef99-15a3-332b-dd78b59444f5.png)
以下キャプチャの''(シングルクォーテーション)内の値が古いプロジェクト名のままになっているため、修正後の新しいプロジェクト名に変更する。
![20221106-223835.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/d1cda7a6-b460-e9a6-2079-08837bfa8109.png)
これを発見するのに1時間くらいかかったので、皆さんはぜひ2秒くらいで終わらせちゃってください。笑

※修正後にクリーン&ビルドは必須です。
![20221106-224606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/4c5cbb53-6103-6255-cb79-594dc7335993.png)
また、これでエラーが消えなければ、プロジェクトを選択した状態で
「右クリック」　→　「Gradleプロジェクトのリフレッシュ」も試してみて下さい！
![20221106-225414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/635740ac-9e7c-1e7d-0df6-a98c5f600ebe.png)
PassLogic のワンタイムパスワードを取得する

```bat:passlogic.bat
@echo off

set LINE[1]=   dBBBBBb dBBBBBb  .dBBBBP.dBBBBP   dBP    dBBBBP dBBBBb  dBP dBBBP
set LINE[2]=       dB'      BB  BP     BP              dBP.BP                   
set LINE[3]=   dBBBP'   dBP BB  `BBBBb `BBBBb  dBP    dBP.BP dBBBB   dBP dBP    
set LINE[4]=  dBP      dBP  BB     dBP    dBP dBP    dBP.BP dB' BB  dBP dBP     
set LINE[5]= dBP      dBBBBBBBdBBBBP'dBBBBP' dBBBBP dBBBBP dBBBBBB dBP dBBBBP   

set SELF=%~n0
set FILE=%TEMP%\%SELF%.%RANDOM%

set USERNAME=（Basic 認証：ユーザー名）
set PASSWORD=（Basic 認証：パスワード）
set HOST=（ホスト）
set PORT=（ポート番号）
set U=（ユーザー名）
set P=
set X=（パターン：以下の表をもとに「1 16 29 20 33 36」のように半角空白を区切り文字として設定）

:: ------------------ ------------------ ------------------
::    1   2   3   4     17  18  19  20     33  34  35  36  
:: ------------------ ------------------ ------------------
::    5   6   7   8     21  22  23  24     37  38  39  40  
:: ------------------ ------------------ ------------------
::    9  10  11  12     25  26  27  28     41  42  43  44  
:: ------------------ ------------------ ------------------
::   13  14  15  16     29  30  31  32     45  46  47  48  
:: ------------------ ------------------ ------------------

setlocal enabledelayedexpansion
  echo.
  for /l %%i in (1, 1, 5) do (echo !LINE[%%i]!)
  echo.
  echo Gathering information, please wait ...
  
  curl -s -u %USERNAME%:%PASSWORD% "https://%HOST%:%PORT%/xxxxx/xxxxx?xxxxx=%U%&xxxxx=xxxxx" > %FILE%
  if %ERRORLEVEL% neq 0 (
    echo An error has been occurred: curl >&2
    exit /b 1
  )
  if not exist "%FILE%" (
    echo File not found: %FILE% >&2
    exit /b 1
  )
  
  set n=
  set i=1
  set t=
  for /f "tokens=*" %%i in ('findstr "randamNumberBoxRadius" %FILE%') do (
    set t=%%i
    set t=!t:^</p^>^</div^>^</td^>=!
    for /f "tokens=4 delims=^>" %%j in ("!t!") do (set n[!i!]=%%j)
    set /a i+=1
  )
  if exist "%FILE%" (del %FILE% > NUL 2>&1)
  
  for %%i in (%X%) do (set P=!P!!n[%%i]!)
  
  set /p ="%P%" < NUL | clip
  
  echo.
  echo ^ P: %P%
  echo.
  set /p =Press any key to close this window. 
endlocal
```

実行結果は以下のとおりです。
![passlogic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29814/92304864-8964-0cfe-ad87-7ada199df549.png)
TypeScript自分用メモ①


某Udemy講座で使うTypeScriptの書き方を振り返るためのメモです。

## TypeScriptの変数&型宣言

静的型付け言語のため、基本的に「: type」の形で型をつける。

定数の場合
const TEISUU: number = 1

変数の場合
let hensuu: string = 'NMR'

変数が複数の型を持つ可能性がある場合（|で型を区切る）
let hensuu2type: number | string = 1

配列の場合は配列の方を指定する。
const numArray: number[] = []

## メソッドの引数の指定と戻り値

引数も型が決められる。
指定した型で提供されない場合はエディタの赤文字、コンパイルエラーで教えてくれる。

function sample(s1: number, s2: string): number {
    //様々な処理
    return 何らかのnumber
}

何でも受け入れられる「: any」を指定することもできる。

## classのprivate化、get/setオブジェクトリテラル

private _hensuu: number 
のように書くと、いわゆるprivateな変数になる。
_はJavaScriptにprivateに相当する機能がないのでprivateに使って欲しい際に書いているらしい。
TypeScriptのようなAltJSでJavaScriptと互換性を持たせるためという記事も見られた。
根拠となるドキュメントはどこなのだろう。


get func() {
    return obj.property
}

これでgetterの役割になる、
外部から呼び出す際は、class.funcのように、getの右に書いたメソッド名でプロパティにアクセスする。
「ソフトウェアテストの教科書」を読んだので、学びをまとめる

## 注意書き

個人の学びのメモとしてまとめている側面が大きいため、読み物としてはあまりまとまっていません。
あらかじめご了承ください。

## 該当の書籍

- 【この1冊でよくわかる】 ソフトウェアテストの教科書　［増補改訂 第２版］
- 布施昌弘：著者 / 江添智之：著者 / 永井努：著者 / 三堀雅也：著者 / 石原一宏：監修 / 堀明広：監修

https://www.sbcr.jp/product/4815608750/

## なぜ読んだのか

- なんとなくソフトウェアのQAに対する解像度が低いような気がしているため、テストに関する体系的な知識を手に入れたい
- 雰囲気でテストを書いていたり書いていなかったりするので、堅牢なソフトウェアを作るための知識を手に入れたい

## 何を学んだのか

- テストを書く際に、何をテストするべきなのかの勘所
- ソフトウェアを設計する際に検討するべき項目
  - 「何をテストするべきか」の項目を知る事が、「設計する際に注意すべきポイント」にもつながる

## 具体的に得た知識

### ソフトウェアの品質とは

ソフトウェアの品質を評価する際の一つの考え方として、以下3点が存在する。

- 当たり前品質
  - ユーザーが最低限、ソフトウェアに期待する品質。これが達成されていなければ、製品として販売するべきではない。
  - 例えばYouTubeで言うと「動画の視聴ができること」など。
- 一元的品質
  - 当たり前品質をMUSTだとした際に、必ずしも満たす必要はないが、満たしていなければユーザーの不満となり得る品質。
  - 例えばYouTubeで言うと「動画を視聴する際に、自由に解像度を選べること」など。
- 魅力的品質
  - 一元的品質をBESTだとした際に、Betterに位置付けられるもの。実現できなくても仕方なくユーザーの不満にはなり得ないが、実現できればソフトウェアの評価を大きく向上させる品質。
  - 例えばYouTubeで言うと、「動画を視聴する際に、クライアントのネットワーク速度から自動的に最適な解像度を選び、配信する」など。

### テストの種類と、各テストケースが期待する目的

テストの種類や考え方は多数存在するが、一つの切り口として以下のような考え方ができる。

- 内部の処理に注目するかどうか
  - ホワイトボックステスト
  - ブラックボックステスト
- 実際にソフトウェアを動作させるかどうか
  - 静的テスト
  - 動的テスト
- 各開発工程に適したテスト
  - 単体テスト
  - 結合テスト
  - システムテスト

## 具体的なテスト手法

### ホワイトボックステスト

一つの機能やモジュール等の単体テストを行う際に用いる手法。

- 制御フローテスト（命令文の処理順序を確認する）
- データフローテスト（データの流れを確認する）

制御フローテストでは、論理構造（条件分岐）の正しさを図る。そのための手法は幾つか存在するが、もし可能なのであれば全ての条件に対するテストをカバーするのが望ましい。
データフローテストでは、使われていない変数等がないかをテストする。こちらはRubyにおいてはあまり意識する必要がなさそう。

### ブラックボックステスト

ブラックボックステストは、主に機能テストとシステムテストにおいて用いる。
内部処理がどのように動いているのかは気にせず、入力や出力が意図した通りに行われているかをテストする。

ブラックボックステストの手法は複数存在するが、以下について記述していく。

- 境界値テスト、同値分割テスト
- デシジョンテーブルテスト
- 状態遷移テスト

#### 境界値テスト、同値分割テスト


仕様の境界となる値に対してテストを行う。例えばユーザー名を入力するフォームがあったとして、

- 数字、英大文字、小文字のみ入力可能
- ５文字以上、１５文字以下のみ有効

が仕様だとするならば、以下のように境界値のテストを行う。

- 4文字、16文字の数字、英大文字、小文字を入力して入力がされない事を確認する
- 5文字、15文字の数字、英大文字、小文字を入力して入力される事を確認する

※境界値のテストを行う際は、値の最小単位に注意する。整数なのか少数なのか等。

#### デシジョンテーブルテスト

デシジョンテーブルテストでは、複数の条件に着目してテストを行う。
複数の条件とは具体的に、複雑な条件分岐の事を指す。

具体的な例として、以下のような仕様をモデルとしてみる。

- 12歳以下は、入場料が600円
- 13歳以上、18歳以下は入場料が900円
- 19歳以上は、入場料が1200円
- 土曜日は入場料が2倍になる（土曜日価格）
- 毎月15日は、年齢を問わず入場料が500円になる（遊園地デー）

このような場合、例えば一例として以下のようなコードが考えられる。

```rb
# Ruby
return 500 if 15日

admission_fee = 0
if 12歳
    admission_fee = 600
elsif 13歳以上且つ１８歳以下
    admission_fee = 900
elsif 19歳以上
    admission_fee = 1200
end

return admission_fee * 2 if 土曜日
admission_fee
```

まず、毎月15日は年齢を問わず一律で入場料が500円になるため、土曜日の場合は500円を返却する。
次に、土曜日の場合は入場料が倍になるため、各年齢層の価格に対して2倍の掛け算を行い、その値を返却する。
15日でもなく土曜日でもない場合は、普段の入場料を返却する。

このように、条件が複数存在し、条件によってリターンを変える必要がある場合は、デシジョンテーブルテストが適している。
以下のような表を作成し、組み合わせ毎の抜け漏れを減らす事ができる。

![スクリーンショット 2022-11-06 23.01.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684929/2b22b8ee-68bb-f9af-e723-1207e7bef3a2.png)

ただし、このデシジョンテーブルは項目が増えるほどテーブルが膨大になっていくため、重複している項目等はうまく消去していく必要がある。

具体的にどのようなテクニックがあるのかは、「ソフトウェアテストの教科書」を参照されたし。

#### 状態遷移テスト

ここは現在学習中のため、理解できたら書く。
餃子に目がない男性が、餃子に特化したレビューアプリを作った

# 前書き
皆さんはこれまで、食べログやぐるなびといったグルメサイトにレビューを投稿したことはあるだろうか。
勝手な推測だが、恐らく投稿したことが無い人の方が少ないという印象を抱いている。
私もその内の一人だ。
私はよく餃子を食べに街に躍り出るのだが、別にレビューを投稿することが苦手なわけではないし、本当に美味しいと感じたお店に対しては、投稿したい気持ちの方が強い時だってある。
ではなぜレビューを投稿しないのか。

***「会員登録」*** があるからだ。

伏見稲荷大社の鳥居の如く立ち並ぶ入力欄を目にしてからは、会員登録をすることをひどくためらうようになってしまった。
時間を削って氏名やメールアドレスなどの数多ある項目が待ち受けているのだと思うと、そこまでして投稿することは合理的ではないと感じてしまうのだ。

それならば誰でも気軽に投稿できるレビューの場を設ければいいではないか。
手始めに私が愛して止まない餃子に特化したWebアプリを制作することとする。

# 制作したWebアプリ
制作したアプリは、下記に掲載されている通りである。
https://sunny-dusk-a6b6eb.netlify.app

https://twitter.com/Yuki_Tamura_85/status/1589255312875597824

添付した通り、***日にち*** 、***店名***、***最寄り駅***、***コメント***を入力して「***レビュー投稿***」ボタンを押下すると、レビューが掲載されるというシンプルな作りである。
（レビュークリアボタンは、便宜上設定したまでである。）
Webアプリのため会員登録など面倒なステップを踏むことなくレビューを投稿することができる。

# 使用したもの
* CodePen
* Netlify
* Vie.js
* iTyped.js

# codepenのソースコード
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="jOKMOLL" data-user="Yuki-Tamura" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/Yuki-Tamura/pen/jOKMOLL">
  餃子専用レビューページ</a> by Yuki Tamura (<a href="https://codepen.io/Yuki-Tamura">@Yuki-Tamura</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 制作を通じて感じたこと
第一にWebアプリの開発は***一筋縄ではいかない***ということだ。
htmlやjavascriptなど、本格的に学習してこなかったことはもちろんだが、基礎となるサンプルのコードを少し書き換えれば完成するような代物ではなく、完成させたい形にするまでにかなりの時間を要した。
今回で言えば、入力欄を追加することで出力されるデータが1つのレビューとしてまとめる方法は、学んだ基礎だけでは望むように機能しないということが分かった。

また、Webアプリだけあって参考となる文書が数多く存在する。
学習の助けになることはもちろんだが、それぞれの筆者ごとにサンプルの書き方が微妙に異なるため、むやみやたらに取り入れようとするとかえってまとまりが無くなってしまう。
自身が作成しているコードを都度見返し、無駄な部分、また追加するべき部分はないかを確認する癖をつけることが重要であると学ぶことができた。

# 後書き
記念すべき初めてのWebアプリ開発は、非常に骨を折る作業だった。
血眼になりながら参考となるサンプルを探し、それをもとにしか作りたいものを作れない私は、やはりシステムのシの字も知らないエンジニアである（エンジニアと言えるのかどうかもまだ怪しい）。

ただ、Webアプリを制作することは、難しいと思うと同時にとても楽しいものであった。
普段スマートフォンで何気なく見ているWebページも、SNS上に添付されている人気餃子店のリンク先も、すべてこのようなコードから生成されているものだと考えると、非常に興味深いものだと感じることができた。

そういった何気なく見ることができる魅力的なWebページを作り上げることができるよう、日々学び続けていきたい。
ESP32 ESP8266で処理を中断できなかったり手のつけようがないときの対処法

筆者の環境
```
OS: Ubuntu 22.04LTS
Terminal: zsh
Python: 3.10.6
ESP8266: B07V3PY2FH
```

今回では`MicroPython`をインストールします。

### ファームウェアの削除

($とか％とか>とかコピーするときに邪魔ですよね。)

```terminal
esptool.py --port /dev/ttyUSB0 erase_flash
```

(`esptool.py`が見つからない場合は`esptool`にしてください。(以降のコマンドも))

```terminal
esptool.py v2.8
Found 1 serial ports
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP8266

~~~~

Enabling default SPI flash mode...
Erasing flash (this may take a while)...

A fatal error occurred: ESP8266 ROM does not support function erase_flash.
```

とエラーが出た。

### ファームウェアの再インストール

```terminal
esptool.py -p /dev/ttyUSB0 --baud 115200 write_flash --flash_mode=dio --flash_size=4MB 0 esp8266-20180511-v1.9.4.bin
```

一番最後の`esp8266-20180511-v1.9.4.bin`はファームウェアです。
[MicroPython公式サイト](https://micropython.org/)からDLしてください。

そうすると
```terminal
esptool.py v2.8
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: c8:c9:a3:66:90:aa
Enabling default SPI flash mode...
Configuring flash size...
Erasing flash...
Flash params set to 0x0240
Took 2.73s to erase flash block
Wrote 591872 bytes at 0x00000000 in 58.0 seconds (81.7 kbit/s)...

Leaving...
Hard resetting via RTS pin...
```

もちろん`picocom`でも

```
picocom /dev/ttyUSB0 --b 115200

picocom v3.1

port is        : /dev/ttyUSB0
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
stopbits are   : 1
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
hangup is      : no
nolock is      : no
send_cmd is    : sz -vv
receive_cmd is : rz -vv -E
imap is        : 
omap is        : 
emap is        : crcrlf,delbs,
logfile is     : none
initstring     : none
exit_after is  : not set
exit is        : no

Type [C-a] [C-h] to see available commands
Terminal ready

>>>
```
Thonyでも
```
MicroPython v1.19.1 on 2022-06-18; ESP module (1M) with ESP8266
Type "help()" for more information.
>>>
```

と、うまくファームウェアの更新に成功しました。

あと全然関係ないですが
```
Leaving...
Hard resetting via RTS pin...
```
ってめっちゃかっこよくないですか？

**参考文献**
[forum.micropython.org](https://forum.micropython.org/viewtopic.php?t=5581)
海外資本の日本法人で好感が持てた上位7社

100%子会社だけでなく、半数出資を含めます。　

 <この項は書きかけです。順次追記します。>
# 好感度上位

## 日本IBM 

Microsoft寄りの自分としては、IBMは敵だという意識で20代は過ごしました。　

30代になって、日本IBMの人と仕事をするようになって、世界のIBMに対して、日本法人がいろいろ努力されているのが見えてきて、好感が持てるようになりました。　

一番最初に親近感を持ったのは、IBMのある工場を見学した際に、シャープの8bit PCで制御していたことを目撃してから。ちゃんと費用対効果を考え、自社製品に拘泥しない体質があると感じたからかもしれない。


## 日本Unisys

アメリカ法人に対して、技術的にも、営業的にも努力されているのを遠目ながら拝見していました。実際には、元日本Unisysの方とは仕事をさせていただきました。日本法人に在籍されている方とは直接お仕事はしていません。ごめんなさい。　

そんなおつきあいのもとで感じられた雰囲気。 

あるお客様への対応が、さらにその会社の顧客までを見た体制が取れているような気がしたのが大きいかもしれない。

## Xerox
実際には富士ゼロックス。後にゼロックスの出資がなくなったのでしょうか。　
いろいろ教えていただきました。

技術で先に進もうという気概を感じたのが大きいかもしれない。


## 日本マイクロソフト　

40年ほど前は、日本マイクロソフトの対応に、いろいろ不満があった。　
ちょうど、最近の、T社、F社、A社などにだいたような。　

知り合いが次々入社し、いろいろな活動で一緒に企画をすると、　
上位３社と同じような努力をされていることがわかった。　

日本IBM、日本Unisisの方々は、私より年上も多く、私がないんか教えるようなことはほとんどなかった。日本マイクロソフトの場合は、私より若い人が多く、私ごときの言うことを、真剣に聞いてくれる若者が多かったのも、高感度があがった理由かもしれない。

## 日本HP 

HPの中部支社が、国際センター２Fにあったころ、営業のWOMさんを時々訪れた。　
HPは測定器と、測定器に付属したHP-PCを利用していた。　

HP UNIX を使わせていただいていた。 

## 日本Apple
Mac ユーザ回で時々Appleのお世話になった。　
日本法人の社長さんが、本社の副社長をされていた頃だったと思う。　

## 日本ボーランド　

知り合いの学生が就職したいと言った。　
東京まで面接に付き合った。　

紹介していただいた技術評論社の社屋を事前に訪問した。
その時のご縁で、技術評論社からマニュアル本をださせていただいたことがある。


# 否定的　

会社名はあげない。日本法人に連絡しても、なしのつぶて。　
結局、海外の本社に英語でメールして解決するような。　

お客様に全然目が向いていない。　
自分たちは給料が高いから偉いと勘違いして、給料の安いお客様を見下して、ちゃんと対応しない人たちをどれほど見てきたことだろう。　
無償のサービスだから、お客様側に訴える利益がなく、違法な行為もいっぱいあったかもしれない。


日本法人なにしてくれちゃうの。　
後で、お聞きすると、日本に全く権限がないようなことだったり、　
自分でも対処が難しいような仕事場かもしれないとは思う。　

自分なら、本社にメールするなり、社長にかけあうなりするのになと思うことはある。　

社長に直接メールなどで主張をしないで、海外の日本法人に努める意味がわかんない。　

# 参考資料　

社外取締役はいかがでしょう

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

で書いているのは、日本法人ではなく、本社の法人のつもりです。補足

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

# 文書履歴(document history)
ver. 0.01 初稿 　20221106