OmniAICreator/Qiita-1.07M huggingface dataset:
【ブログ作りたい方必見】Reactでmdファイルを使わずに、Qiitaと同じようにMarkdownで記事を書く方法

皆さんこんにちは！

つい１ヶ月ほど前ぐらいからReactの勉強をし始め、今ではReactのフレームワークGatsby.jsで遊んでいます。

そんなReactで面白いパッケージを発見したのでご紹介したいと思います。

その名は、、、

**react-markdown**です！

これはQiitaと同じようにMarkdownで記事を書くことが可能です！

世の中便利になりましたね。

実装も全く難しくありません。

パッケージのインストール時間を合わせても１０分いかないくらいで実装できます。

説明はこの辺にして早速始めていきましょう！

#はじめに#

QiitaのMarkdownすべてが実装できるわけではありません。

```javascript
console.log('markdown')
```

例えば、このようなコードを記載するMarkdownは使えません。

もしかしたら実装できるかもしれないのですが、調べた限り方法は見つかりませんでした。

知っている方がいたらぜひコメント欄に教えて下さると助かります。

#必要パッケージのインストール#

まずは必要なパッケージをインストールします。

```powershell
npm install react-markdown remark-gfm github-markdown-css
```

#react-markdownの設定#

```jsx
import 'github-markdown-css/github-markdown.css';
import React from 'react';
import ReactMarkdown from 'react-markdown';
import gfm from 'remark-gfm';

const Markdown = () => {
  const markdown = `
  **aiueo**

  # aiueo
  `
  return(
    <React.Fragment>
      <ReactMarkdown className="markdown-body p-3" remarkPlugins={[gfm]} children={markdown} />
    </React.Fragment>
  )
}

export default Markdown
```

まず初めに気を付けることはmarkdownの記述を**""**（ダブルクォーテーション）ではなく、**``**（バッククォーテーション）で行っているということです。

ダブルクォーテーションだと正しくmarkdownが読み込まれないので気を付けください。

``remarkPlugins``はよくわかんないっす（笑）。

一応公式ドキュメントを載せておきます。

[react-markdown - npm](https://www.npmjs.com/package/react-markdown)

``children`` にはMarkdownで記述したものを指定します。

最後に``import 'github-markdown-css/github-markdown.css'``でCSSをインポートしてください。

これでMarkdownでブログを書くことが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/2181c67e-5483-e71f-14f7-b67f286a1f9a.png)

実際に書くとこんな感じです。

意外と簡単に実装できました。

ただ、``import 'github-markdown-css/github-markdown.css'``これがないとQiitaのようなMarkdownを記述できないところで少し躓きました。

皆さんはコピペで十分です！

以上、「【ブログ作りたい方必見】Reactでmdファイルを使わずに、Qiitaと同じようにMarkdownで記事を書く方法」でした！

Thank you for reading
Laravel Sanctumでログインは成功するが、要認証APIが401 Unauthorizedエラーを返す

# 問題
LaravelでAPIを作ってて、Sanctumを利用してユーザー認証を実装し、開発環境では動作しました。そこで検証環境に持って行ったところ「ログインは成功するが、そのあと認証が必要なAPIにアクセスすると『401 Unauthorized』エラーで弾かれる」という現象が発生しました。

# （私の場合の）原因
1. そもそも開発環境用の.envだけ設定してて、検証環境用の.envにSanctum周りの設定するの忘れてた
2. 1を受けて設定したものの、.envのSANCTUM_STATEFUL_DOMAINSの記載が間違っていた

原因1に関しては「実装できた～✌」と完全に気が抜けてましたね……スーパーアホでした😅 
原因2に関してはDocker上で開発してて、雑にlocalhostで設定していても動いてしまっていたので、仕様をちゃんと理解できてなかったのが原因です。

## 調査
.envの反映し忘れの線はすぐに当たりましたが駄目。ブラウザの開発者ツールで401しか出ず、Cookie周りも正常動作してるように見えました。「（デプロイ自動化してないので）検証環境のライブラリ自体にロガー仕込むの面倒くさい」と、ググり倒したり設定弄り回したりあがいてみましたが、これも駄目でした。
ただ調べる過程で[この記事](https://qiita.com/ksrnnb/items/d2b73a6bf7dccde90446)を見かけて、どのクラスに仕込めばいいのか当たりがつきました。大変助かりました🙏 

```php
// \vendor\laravel\sanctum\src\Http\Middleware\EnsureFrontendRequestsAreStateful.php
    public static function fromFrontend($request)
    {
        $domain = $request->headers->get('referer') ?: $request->headers->get('origin');

        if (is_null($domain)) {
            return false;
        }

        $domain = Str::replaceFirst('https://', '', $domain);
        $domain = Str::replaceFirst('http://', '', $domain);
        $domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";

        $stateful = array_filter(config('sanctum.stateful', []));

        return Str::is(Collection::make($stateful)->map(function ($uri) {
            return trim($uri) . '/*';
        })->all(), $domain);
    }
```

メソッド名から察しがつくかと思いますが、Webブラウザからのアクセス（Session使える）か、CLIアクセス（Session使えない）かの判定ですね。
「refererあるいはorigin、SANCUM_DOMAIN_ORIGINSを加工した上で比較してるんだな」というのが分かって、Str::isも調べてようやく、**SANCTUM_STATEFUL_DOMAINSに「www.」のないドメインを登録してて、$domainとマッチしてない**ことに気づきました。.envの他の項目とごっちゃになったか、省略可能だろうと当てずっぽうに設定した線が濃厚です😅
「www.」を含めたドメイン名を設定することで無事動きました。

# 感想
ググった限り、このトラブルはそこそこある上に、原因となる要素が多いんで、StackOverFlow等でも「更新後の.envちゃんと適応してる？」とか「sessionタイプをcookieにしろ（注：デフォルトのfile設定で動きます。誤解してる人の書き込みがあるので注意）」等、場当たり的なアドバイスが多いです。チェックリストの必要性を感じましたね……誰か作ってください。（怠慢）
またsession管理がファイルの場合だと書き込み権限絡みで失敗するパターンもあるみたいなんで、この問題にハマっている人はチェックしてみてください。
それと身も蓋もないですが「（検証環境とはいえ）APP_DEBUG=trueにしたらもっと早く分かったんじゃね」と今書いてて思いましたw デプロイが手作業なこと、[マルウェア問題の記事を読んだ直後](https://qiita.com/reopa_sharkun/items/f3819b2e8727728da82a#comment-752be52537563f233e73)で、検証環境でAPP_DEBUG=trueするのに抵抗があったので、思いついても実行出来たかどうか微妙ですが……。

# 🙏Laravel公式ドキュメント翻訳者への支援のお願い
Laravelの公式ドキュメントの日本語版である[ReaDouble.com](https://readouble.com/)を運営されている川瀬裕久氏が、広告収入の低下と持病の悪化のため、翻訳プロジェクトを継続することが困難になり、[GitHub sponsorsを募集しています。](https://github.com/sponsors/HiroKws) 日本のLaravelユーザーでここを見たことない人はいないと思うので、もし恩義を感じているならば是非支援のほどお願いします。私も支援させていただいております
はじめてのさわりだけの「なでしこ」　おもしろい！！

情報処理学会誌の「情報処理」2021年5月号巻頭コラムに [クジラ飛行机](https://qiita.com/kujirahand) さんの
[「かつてなく楽しくプログラミング言語が開発できる時代に」](https://note.com/ipsj/n/nf1d33f6be0c6)　が掲載されていました。
今年度（2021年度）からの中学の教科書（教育図書）でも扱われているようです。

「なでしこ3」をさわりだけやってみました。

[https://nadesi.com/top/](https://nadesi.com/top/) からたどって
[なでしこ3 Web簡易エディタ](https://nadesi.com/doc3/index.php?%E3%81%AA%E3%81%A7%E3%81%97%E3%81%933%E7%B0%A1%E6%98%93%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF)  を開きます。

#####最初はサンプルにあったものをそのまま入力して実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/4733eaf0-cbcd-cc62-290a-0ba715a43a47.png)

これは面白そう。

#####次に [なでしこ３文法の解説](https://nadesi.com/v3/doc/index.php?%E6%96%87%E6%B3%95) とかを見ながら分岐処理をやってみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/744f242b-d267-fe9f-ed17-423cc1a49a94.png)

#####繰り返しはどうかな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/5d4929d2-f42c-9806-6b96-d36b2f3d3d9b.png)

#####描画とかもできるみたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/d356546c-9883-c9ad-808f-8d247ee90ea9.png)
ZIPファイルの中身を解凍する

先日、windowsのCドライブのディスクが枯渇する問題がありました。
原因は凡ミスでTEMPファイルを大量生成していたのですが。。。
その関連でCドライブの%TEMP%にファイルを作成せずにZIPファイルを解凍する方法があったので書き込みます。

まず、ZipArchiveを使えるようにするため、以下を参照します。

- System.IO.Compression
- System.IO.Compression.FileSystem


![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1266682/659c4a20-31d0-f7ae-368c-8d19e07b717a.png)

そして、以下のコードを書きます。

```C#
	var file = @"comp.zip";
	using (ZipArchive archive = ZipFile.OpenRead(file))
	{
		var f = archive.GetEntry("comp.txt");
		var ms = f.Open();
		using (var fileStream = new FileStream("output.txt",
			FileMode.CreateNew, FileAccess.ReadWrite))
		{
			ms.CopyTo(fileStream);
		}
	}
```

これで、comp.zipにあるcomp.txtをoutput.txtに書き出すことができます。
Chrome Canary をダウンロード・インストールしてみる

# はじめに
みなさんChrome使ってますか？私は愛用しております。
さて、そんなChromeですが、いつでも最新版な種類がございます。それがChrome Canaryです。それでは実演していきましょう。

せっかちな方は[ここ](#ダウンロードインストール)まで飛んでください。

# なんだそれ

先程も言ったとおりにCanaryはいつでも最新です。公式ページを見てみると

> + 次期バージョンのウェブに合わせたウェブサイト開発
> + 最先端のウェブ プラットフォーム API のテスト
> + 毎日更新

だそうです。最新のAPIとか使って作業している方からしたらすごいことでしょう。
最新版を使いたいがために私は長らくChromiumを使っていたのですが、それは手動で更新する必要があって結構面倒なんですよね。そんな悩みが解決できました。ﾔｯﾀ-


# ダウンロード&インストール

https://www.google.com/intl/ja/chrome/canary/

それではダウンロードしていきましょう。上のリンクにアクセスします。
![Canaryのダウンロードページ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/ff71a046-314e-dfb8-751a-17c7bb048f98.png)

画面中央にある`Chrome Canary をダウンロード`をクリックします。
そうすると別ページに飛んでダウンロードが開始されます。

![セットアップがダウンロードされました](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/f1caef50-be0f-7b27-3c0d-6f60498c967c.png)
ダウンロードが終わったらexeファイルをクリックします

※`この種類のファイルはこのコンピュータに損害を与える可能性があります`と出てくる場合がありますが、`保存`をクリックしてください。

![インストール終了](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/2d4a8d9a-f9bc-388b-82ea-f5cdd08ad98c.png)
exeをクリックして暇を潰しながら待っていると自動でこの画面が表示されました。通常のChromeと変わらないおなじみのやつですね。

私の場合Chromeをすでにお持ちだったのでログインをします。

![IMG_2968.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/758439d3-9148-3e5f-f6f1-8e4ddf859807.jpeg)
正常に使えるようになりました。
※右上のエラーはただの警告でした。

# バージョンの確認
![Canary](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/9fdcd220-a811-f019-2a14-c9e43f0d967a.jpeg)
Canaryのバージョンです。92.0.4479.3でした。

![Chrome](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/2c6a34ea-bd90-6e4c-7ba2-b42846f594cb.jpeg)
通常のChromeです。90.0.4430.2でした。こう見ると差がよくわかります。

![Chromium](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/80c82267-e76f-8422-ecc7-75c97615b453.jpeg)
同日に手動でダウンロードしたChromiumです。92.0.4481.0でした。Chromiumは更新が一分前とかそんなこともあるので当たり前っちゃ当たり前でしょう。そもそもChromeはChromiumに足を生やしたみたいなそんな感じなので。もちろんChromiumも素晴らしいですよ。だってほぼ変わらないですから。

# おわりに

まだ使い始めて1日目ですが、使用感はノーマルChromeと変わらずに、且つ最新機能も楽しめるといったワンダフルでエキサイティングなブラウザだと感じています。
ちなみにこの記事は早速Canaryで書いています。

~~使用した感想などこれから記事にしようと思ってます。~~
SQL トランザクションを貼る 個人メモ

# 目的

- MySQLでトランザクションを貼る方法をメモ的にまとめる

# 方法

- BEGIN句とCOMMIT句を用いることでトランザクションを貼ることができる。
- 下記に例を記載する。

    ```sql
    BEGIN;

    ここにトランザクションを用いて実行したいSQLを記載する
    
    COMMIT;
    ```

- トランザクション処理をコミットしたくないときは下記のように`ROLLBACK`と記載する。

    ```sql
    BEGIN;

    ここにトランザクションを用いて実行したいSQLを記載する
    
    ROLLBACK;
    ```
個人開発で稼ぐことについて効率化を考えてみる

## プログラマーだけではなくランチェスター戦略をとって個人開発をしようって話

---
### ターゲット

- 人から使われないボツアプリを作りたくない人
- 個人開発で利益を産むようにしたい人

---

**まず**

「個人開発で少しでもお金が産めたら良いな〜」と思っていませんか？

---
#### 理想との乖離

**イメージ**
あまり稼げないし本業を進めるのに足枷になりそう

3ヶ月ほど時間をかけて無駄にしてしまうもの多くある
→その時間も学習になるからいい

なんて考えていませんか？

---
### MOTTAINAI

---
個人開発でのよくあるアドバイスは
---
- 自分の解決したい問題にフォーカスすべき
- トランザクションが多くなるものにすべき
- 技術にチャンレンジすべき

など

---

アドバイスがバラバラ

---
### 理由はそれぞれ目的が違うから！
- バズらせるため
- 新技術をためす砂場を設けるため
- お金を産むため
- キャリアに繋げるため
- 自分が困ってる課題を解決したいなど...

---
#### 例をあげるなら

---
勉強のためのポートフォリオ
例）　技術を極めてみた系
![スクリーンショット 2021-04-17 17.27.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/61d641f3-4938-499b-2cdc-18b4d82ee636.png)
（画像はたまたま拾ったすごいなと思ったもの）

---

### 技術的な強みを活かした例

https://enno.jp/

https://ccd.cloud/

みたいな
お助かりまくりサイト

---
これらは成功例！

エンジニアとしてよくある間違ったイメージ
***良いものを作れば勝手にユーザーが後から集まる***

---
### 広告運用の現状

スマホアプリなら
1ダウンロード4~8円程度らしい
つまり
1000DL　→　5000円ほど

**まじか**

---
### Webでのバナー広告

1日3万アクセス →　月30万ほど
月間3,000pv　→　1000円ほど

**く〜〜〜**

---

正直、仕事をやめて良いレベルまでは程遠い

自分のアプリが成功してて
月100万入るから好きなことだけしてるわ〜
なんて言ってみたい

#### 人を惹きつけるコンテンツと勝てる戦略が必要

---
今回は
#### 安定的な収益があってほどほどの時間的努力で達成することが目標

---
### 開発　≠　プロダクト制作

---

プロダクト制作　= 　{

　　　課題理解、市場調査、企画、戦略、データ収集、
　　　データ設計、**プログラミング**、広報、
　　　ブランディング、集客、セールス、サポート・・・・

}

---
#### プロダクト制作は知らない事とTry&Errorの嵐

けどどうせやるなら
プロダクト作成という学びを楽しみながら開発しませんか?

---
### やり方は無限にあるので一旦戦略だけに絞る

---
### ランチェスター戦略

第一次世界大戦での航空戦から生まれた戦略

https://bizhint.jp/keyword/164952

---
簡単にいうと

強者には強者の戦い方があり
弱者が強者に勝つためには
弱者は戦いの場を選ばないといけないという理論

```
弱者 ≠ 負ける
弱者 = 勝つための手段が強者と違う
```

---
#### 個人開発の強み

企業では入れないニッチ産業に入れる
企画から実行までのスピード
自分が働いてるだけなので何度でも失敗できる

#### 結論：
ニッチなニーズの中で
他になかった需要を埋めて
サブスクや買い切りの形でお金を産むほうが現実的

---
つまり

ペルソナをニッチに細かく設定する
ユーザーがお金を出しても使いたくなるほど
価値を産むことを考える

---
- PVを重視するのを止める
- 多少は反対意見が出るようなものでも良い
- 少数に刺さるコンテンツ

---
#### 量よりも質
大手の会社が考えるような
すでにお金が飛び交っているようなサービスは避けたい

例えば
お医者さんに対してのERPパッケージや
男女のマッチングサービスなど

大企業たちがキャッシュでの殴りあいをしている市場に入っても踏み潰されるだけかもしれません

---
よりは

- 一部のインフルエンサーに刺さるSNSツール
- 一風変わった趣味のマッチングアプリ
- 市場規模の小さい業界のERPなど
- 突発的な事象に紐付けたサービス

（既存サービスの障害で突然現れる需要、
　感染症に対しての予防サービス）

---
### ゴール設定は重要
- 何を目的にしているのか
- どのくらいの期間を想定しているのか
- 長期目標、中期目標
- 得られるメリットの査定

ピボットは時間がかかるし、もったいない

https://www.hrpro.co.jp/glossary_detail.php?id=176#:~:text=%E3%80%8C%E3%83%94%E3%83%9C%E3%83%83%E3%83%88%E3%80%8D%EF%BC%88pivot%EF%BC%89%E3%81%A8,%E3%81%A8%E3%81%AF%E9%99%90%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82

---
### まとめ

個人開発で稼ぐことのポイントを解説しました

目的・ゴール設定が大事
広告モデルは落とし穴

---
### エンジニアは天才です

---
これを見るひとは大抵が
エンジニアか、ITに興味ある人でしょう

普段なにげなくやっているエンジニアリング
「簡単なこと」と思っていること
日本全体で見た時にどれだけの人ができるでしょうか？

---
それぞれの個性というだけかもしれませんが
個人的には、ITが好きくらいで才能の持ち主だと思ってます

その才能のあるあなたが挑戦しないのは
**MOTTAINAI**

---
#### ソフトウェアエンジニアに備わるアドバンテージ
- 自分でMockを作れてユーザー検証などもしやすい
- サービスを形作りローンチできる
- 普段から課題解決ばかりしている
- 運用資金も作りやすい（給料水準）

---

#### エンジニアにチャレンジして欲しい

---

個人開発について発信しています！
Twitterもフォローください
[@1026NT](https://twitter.com/1026NT)
![Twtter](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/51cb0334-9736-cc41-eff7-d11eb6fe1e3a.jpeg)


---
参照：
http://kbn1053.hatenablog.com/entry/2017/12/10/225528
https://qiita.com/FaLiP_lvsg/items/529b88551cc7c1da9f01
https://note.com/2zn01/n/ne5356d16f25b
RSpecをインストール

#【RSpecをインストール】

Dockerで開発したRailsアプリのテストコードを書きます。
RSpecを使用するのでインストール手順を備忘録として残します。

##RSpecをインストール

Gemfileに下記のように追記し、
$ docker-compose build を実行する。

```:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'rspec-rails', '~> 5.0.0'
end
```
次に、$ docker-compose run web bundle exec rails g rspec:install を実行し、RSpecに必要なディレクトリや設定ファイルを作成する。

```
//実行結果

Running via Spring preloader in process 26
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```

 ※ spec/spec_helper.rb は、全体的な設定を記述するファイル
 ※ spec/rails_helper.rb は、Rails特有の設定を記述するファイル
バッチファイルに引数が無ければ要求する

Y子です。
__[昨日](https://qiita.com/koiwaiwaiko/items/6d2bcb5f02ef69ca0836 "バッチファイルに引数が無ければ終了する")__ に引き続き、引数チェックシリーズです。

# 概要・用途
引数の有無を確認し、無い場合は対話式で入力を求めます。
_【[確認環境：Windows 10 Home (Bld. 19042.867)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_

# コード
## (1) シンプルな例
バッチファイルに引数を与えれば、引数を使います。
引数が無ければ、対話式で標準入力からの入力を求め、同じ変数に格納します。

```bat:argument_interactive1.bat
@echo off
rem 変数初期化
set str_arg=

rem 引数がない場合は対話モードで取得
if "%~1"=="" (
  set /P str_arg="引数は? : "
) else (
  set str_arg=%~1
)

echo 引数：%str_arg%
pause
```

まず、引数「`aaa`」を与えて実行した場合。

```:実行結果：引数あり
> argument_interactive1.bat aaa
引数：aaa
続行するには何かキーを押してください . . .
```

次に、引数無しで実行し、聞かれてから「`aaa`」を入力した場合。

```:実行結果：対話式で入力
> argument_interactive1.bat
引数は? : aaa
引数：aaa
続行するには何かキーを押してください . . .
```

ただ、聞かれたときにEnterを押してしまうと、結局は変数に空文字が渡ってしまうので、エラー処理としては不十分です。

```:実行結果：対話式でも空欄
> argument_interactive1.bat
引数は? : 
引数：
続行するには何かキーを押してください . . .
```

## (2) 入力させるまで絶対にあきらめない例
そこで、入力があるまで無限に入力を求めるよう、修正してみました。

```bat:argument_interactive2.bat
@echo off
rem 変数初期化
set str_arg=

:label_top

rem 引数がない場合は対話モードで取得
if "%~1"=="" (
  set /P str_arg="引数は? : "
) else (
  set str_arg=%~1
)

if "%str_arg%"=="" (
  echo 引数は絶対に必要です
  goto :label_top
) else (
  echo 引数：%str_arg%
)
pause
```

引数なし、標準入力も絶対に入れない、という人はこうなります。

```:実行結果：対話式で絶対にあきらめない
> argument_interactive2.bat
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? :
引数は絶対に必要です
引数は? : bbb
引数：bbb
続行するには何かキーを押してください . . .
```

# おわりに
エラー処理だいじ。

では！
Python3: メールの送信 （添付ファイル付き）

こちらのプログラムを改造して、添付ファイルを送るようにしました。
[Python3: Starttls でメールの送信](https://qiita.com/ekzemplaro/items/c248b52a6f36947af080)
attachements/linux_logo.gif というファイルを添付するサンプルです。

```py:coreserver_attache.py
#! /usr/bin/python3
# -*- coding: utf-8 -*-
#
#	coreserver_attache.py
#
#						Apr/17/2021	
# --------------------------------------------------------------------
import	os
import	sys
import	socket
from dotenv import load_dotenv
import	email
from email.mime.text import MIMEText
from email.utils import formatdate
from email.message import EmailMessage
import imghdr
# --------------------------------------------------------------------
from send_starttls import send_starttls_proc
# --------------------------------------------------------------------
def attach_image_proc(message,img_data,filename):
    try:
        message.add_attachment(img_data,maintype='image',
            subtype=imghdr.what(None,img_data),filename=filename)
    except Exception as ee:
        sys.stderr.write("*** error *** in message.add_attachment ***\n")
        sys.stderr.write(str(ee) + "\n")
#
    return message
# --------------------------------------------------------------------
def create_message_proc(mail,file_attach):
	message = EmailMessage()
	contents = 'Hello, Good Afternoon! on Apr/17/2021 PM 20:21\n'
	contents += 'Apr/17/2021 PM 20:03\n'
	contents += 'こんにちは。\n'
	contents += 'python3\n'
	contents += ' ' + socket.gethostname ()

	message.set_content(contents)
	message['Subject'] = 'Hello Apr/17/2021 PM 20:21'
	message['From'] = mail['from']
	message['To'] = mail['to']
	message['Date'] = formatdate ()
#
	fp = open(file_attach,'rb')
	img_data = fp.read()
	fp.close()
#
	for suffix in [".jpg",".png",".bmp","gif"]:
		if (file_attach.endswith(suffix)):
			message = attach_image_proc(message,img_data,file_attach)
#
	return message
# --------------------------------------------------------------------
sys.stderr.write ("*** 開始 ***\n")
dotenv_path = '.env'
load_dotenv(dotenv_path)
mail = {}
mail['server'] = os.environ.get("SERVER")
mail['port'] = os.environ.get("PORT")
mail['usr'] = os.environ.get("USR")
mail['password'] = os.environ.get("PASSWORD")
mail['from'] = os.environ.get("FROM")
mail['to'] = os.environ.get("TO")

file_attache = "./attachements/linux_logo.gif"

message = create_message_proc(mail,file_attache)

send_starttls_proc (mail,message)
#
sys.stderr.write ("*** 終了 ***\n")
# --------------------------------------------------------------------
```

次のファイルはこちらです。
[Python3: Starttls でメールの送信](https://qiita.com/ekzemplaro/items/c248b52a6f36947af080)

```text
send_starttls.py
.env
```
API GatewayのOutput

#はじめに
API Gatewayの勉強のoutputように書きます。また今回は、API Gatewayのみで行っているのでlambdaは今回使っていません。見たら実践できるようにできるだけ書きますので、もしよければフォローお願いします！
#前提として
* python を基本コードとして使います
* AWS マネジメントコンソールを登録している前提で始めます

#API Gatewayを製作する
AWSのマネジメントコンソール画面に行き、検索バーから「API Gateway」を選択します。そして、サンプルAPIを作成します。設定は、以下のようにし、初めのAPIタイプは、REST APIを選んでください。![api作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/92c05ed1-8784-a464-de29-950da65d6752.png)

その後、「アクション」を押して、「リソースの作成」し、リソース名は任意で大丈夫です。同様に「メソッドの作成」から「GET」選び、統合タイプを、「Mock」を選択します。![api設定2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/3b99f040-c303-6cc2-5b46-274abf645cb9.png)
次に、GETメソッドの実行を行います。
![getメソッドの実行.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/a645797c-fdc1-2953-6ecf-f455ce347e55.png)
「統合レスポンス」を選択し、「マッピングテンプレート」の「application/json」に以下のコードを入力します。

```
{
    "statusCode": 200,
    "body" : {
        {
            "report_id": 6,
            "report_title": "おはようございます"
        }
    }
}
```
この状態で、「メソッドの実行」に戻り「テスト」を行います。以下が、実行結果です。![api結果1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/641fafd8-d3fe-563b-0064-ae77d00027e9.png)![api結果2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/1c833492-7fe5-599c-b272-10bfc87110c2.png)
#Mockとは
Mockとは、一言でいうとテストに必要な部品の値を擬似的に設定するものです。
今回は、テストプレイですので、Mockを使います。
#デプロイを実行する
次は、デプロイしていきます。設定は、以下のようにします。するとurlが作成されます。![dev2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/6b80a397-b23d-444a-1ef5-c684beceb52a.png)
![dev_url.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/4997d01e-706b-f5fc-2a0d-c2cb76e76b86.png)
作成したurlを検索すると、コードの内容が出力できます。
![出力結果.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/405e23ac-15b5-9d77-b47c-83a64798f8e0.png)
以上でデプロイ成功です！
#今回の流れの概要
![完成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/fc779690-ea59-88f1-c3ea-35ca96ec74af.png)
FactoryBotのアソシエーション



```rb:terminal
Failures:

  1) Item#create image,item_name,description,category_id,status_id,prefecture_id,delivery_fee_payment_id,delivery_prepare_id,priceの値が存在すれば登録できること
     Failure/Error: expect(@item).to be_valid
       expected #<Item id: nil, item_name: "b21ywo", description: "frec268o37r2ulb917hgti5vwbf7hbt07sxp05ezpt8ad2z1iv...", category_id: 2, status_id: 4, delivery_fee_payment_id: 2, prefecture_id: 44, delivery_prepare_id: 4, price: 4723291, user_id: nil, created_at: nil, updated_at: nil> to be valid, but got errors: User must exist
     # ./spec/models/item_spec.rb:11:in `block (3 levels) in <top (required)>'
```

###エラー文[but got errors: User must exist]とは

ユーザー情報がないよっといっています。

解説
-

|条件|モデル名|組んでいるアソシエション|外部キー|
|--|---|----|--|
|①アソシエーション|user|has_many :item|なし
|②外部キーを保持|item|belongs_to :user|あり

解答
-

上記の中でitemモデルのテストを行う場合は外部キーを保持しているモデルのテストのファクトリーボットにアソシえーション設定が必要になってきます。

```ruby:ruby
FactoryBot.define do
  factory :item do
    # image { Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/20210327-085606.png") }
    item_name {Faker::Lorem.characters(number: 6, min_alpha: 1, min_numeric: 1) }
    description {Faker::Lorem.characters(number: 100, min_alpha: 1, min_numeric: 1) }
    category_id {Faker::Number.between(from: 2, to: 11)} # 2〜11のいずれかがランダムに表示
    status_id {Faker::Number.between(from: 2, to: 6)} # 2〜6がランダムに表示
    prefecture_id {Faker::Number.between(from: 2, to: 48)} # 2〜48がランダムに表示
    delivery_fee_payment_id {Faker::Number.between(from: 2, to: 3)} # 2〜3がランダムに表示
    delivery_prepare_id {Faker::Number.between(from: 2, to: 4)} # 2〜4のいずれかがランダムに表示
    price {Faker::Number.between(from: 1, to: 9999999)} # 1〜9999999のいずれかがランダムに表示
    association :user
  end
end
```
AtCoder 第二回日本最強プログラマー学生選手権 参戦記

# AtCoder 第二回日本最強プログラマー学生選手権 参戦記

難易度絶壁の直前に数学問題置くのやめて……. 久々の三桁パフォ…….

## [JSC2021A - Competition](https://atcoder.jp/contests/jsc2021/tasks/jsc2021_a)

3分で突破. 書くだけ.

```python
X, Y, Z = map(int, input().split())

print((Y * Z - 1) // X)
```

## [JSC2021B - Xor of Sequences](https://atcoder.jp/contests/jsc2021/tasks/jsc2021_b)

3分で突破. 書くだけ.

```python
N, M = map(int, input().split())
A = set(map(int, input().split()))
B = set(map(int, input().split()))

print(*sorted(A ^ B))
```

## [JSC2021C - Max GCD 2](https://atcoder.jp/contests/jsc2021/tasks/jsc2021_c)

9分で突破. B≤2×10<sup>5</sup> だからシングルループは OK. GCD を a と置くと x は A 以上の最小の a の倍数とし、y は x + a として、y ≤ B であれば、その a は答えとして有効であるということになる. あとは B までループを回してやれよい.

```python
A, B = map(int, input().split())

for a in range(1, B + 1):
    x = (A + (a - 1)) // a * a
    y = x + a
    if y > B:
        continue
    result = a
print(result)
```

## [JSC2021D - Nowhere P](https://atcoder.jp/contests/jsc2021/tasks/jsc2021_d)

64分で突破. [Wolfram|Alpha](https://ja.wolframalpha.com/) に `g(1)=P-1, g(n+1) = g(n) * (P-2)` を入力したら *g*(*n*) = (*P* - 1)(*P* - 2)<sup>*n*-1</sup> と教えてくれたので解けた.

```python
m = 1000000007

N, P = map(int, input().split())

print((P - 1) * pow(P - 2, N - 1, m) % m)
```
pandas結合

# 結合方法
- concat結合
 - シンプルな結合
- merge結合  
 - 内部結合
 - 外部結合
 - 左結合
 - 右結合

使うdf

```python
import pandas as pd

df1 = pd.DataFrame({
    "ID" : [1,2,3],
    "Country" : ["鈴木","中村","小島"],
})


df2 = pd.DataFrame({
    "ID" : [2,3,4],
    "Address" : ["Hikone","Tokyo","Nagoya"],
})
```
![スクリーンショット 2021-04-17 19.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/feecc8c3-00ec-f1bb-5821-210bd40d345f.png)


# concat結合
シンプルに右にくっつくか、下にくっつくか。

右にくっつく

```python
concat_df = pd.concat([df1, df2], axis=1)
```

![スクリーンショット 2021-04-17 19.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/3ae47663-ea75-f54d-503a-4487c2a4c794.png)


下にくっつく

```python
concat_df = pd.concat([df1, df2], axis=0)
```
![スクリーンショット 2021-04-17 19.58.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/36494c29-4324-fd63-b187-4e7b876466a1.png)

# merge結合
キー(ID)に紐づいて結合する。


## 内部結合
2つのdfのキーが一致するデータのみ抽出

```python
inner_df = pd.merge(df1, df2, on="ID", how="inner")
```
![スクリーンショット 2021-04-17 20.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/5e2fc87a-3792-0f80-bc7f-c017994ac9ee.png)


## 外部結合
2つのdfのキーに紐づくデータを全て抽出

```python
outer_df = pd.merge(df1, df2, on="ID", how="outer")
```

![スクリーンショット 2021-04-17 20.09.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/52893feb-e01e-bcd6-b5eb-e0a8fca5800d.png)


## 左結合
（引数で）左指定のdfのキーに一致するデータを抽出

```python
left_df = pd.merge(df1, df2, on="ID", how="left")
```

![スクリーンショット 2021-04-17 20.10.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/e5972686-6ee7-d233-4ad3-aa992909724f.png)



## 右結合
（引数で）右指定のdfのキーに一致するデータを抽出

```python
right_df = pd.merge(df1, df2, on="ID", how="right")
```

![スクリーンショット 2021-04-17 20.13.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/e473ac63-87eb-9dcb-45d0-0d4a013dc1a2.png)


漏れなくデータを結合したいのか、どこに欠損を出したくないのか、で使い分ける感じですかね。
Anacondaをアンイストールしたらコマンドプロンプトが動かなくなった

参考(https://www.fixes.pub/computer/302632.html)

cmd起動直前にanacondaの処理を挟む処理を入れているのだが、Anaconda自体がアンイストールされているためエラーで落ちるからコマンドプロンプトも落ちてしまうっぽい。　Anaconda(´・ω・｀)…

# 修正方法
Powershellで以下を実行する

```
Reg Delete "HKCU\Software\Microsoft\Command Processor" /v AutoRun /f
```
deviseを介したユーザー管理機能

gemファイルにdeviseを入力してbundle installするだけで使用できると思っていたので、記事にしておきます。


```gem 'devise'
```
をgemfileに入力してbundle install

```rails g devise:install
```
上記をターミナルに入力して実行しないとしようできません。

```rails g devise モデル名
```
でdeviseを介したモデルを作成できます
USBタイプの usbrh 温湿度センサーの使用

USBタイプの usbrh 温湿度センサーを使用する方法です。

Ubuntu（debian）系なら簡単に下記コマンドで値を取得することができます。

````bash:install_usbrh.sh
#!/usr/bin/bash

sudo echo ;

git clone https://github.com/osapon/usbrh-linux.git ;
cd usbrh-linux/ ;
sudo apt install build-essential ;
sudo apt install libusb-dev ;
make ;

sudo ./usbrh  ;
````

結果

````
22.15 51.36
````

USB の都合上 sudo が必要なのがなんともですが、ルートになって、cron で実行するなどすれば良いでしょう。

####参考リンク

- [USB温度・湿度計モジュール\(完成品\) \- USBRH\-FG \- ネット販売](https://strawberry-linux.com/catalog/items?code=52002)
- [USBRH \- 温度・湿度計モジュール関数リファレンス](http://strawberry-linux.com/products/usbrh/usbrh)
- [【 lsusb 】コマンド――USBデバイスの一覧と詳細情報を表示する：Linux基本コマンドTips（273） \- ＠IT](https://www.atmarkit.co.jp/ait/articles/1901/17/news028.html)
- [diffで差分のみ抽出する \| ITを使っていこう](https://it-ojisan.tokyo/diff-only-list/)
- [BASHシェルスクリプトで「キー入力待ち」プロンプトを実装する \| DevelopersIO](https://dev.classmethod.jp/articles/waiting-for-your-input-with-read-command/)
- [USBシリアルデバイスの権限設定 \- mondayboy's diary](http://mondayboy.hatenablog.com/entry/2015/05/05/182610)
- [Ubuntu日本語フォーラム / USBへのアクセス権限について](https://forums.ubuntulinux.jp/viewtopic.php?id=7491)


以下、自分的メモです。

````bash:check_usb_vender.sh
#!/usr/bin/bash

# ======================================================
#
# ======================================================
echo "please remove usb cable";
echo "Are you ok ? [ ENTER ]"
read -p "Hit enter: "
lsusb > lsusb_first.txt ;

# ======================================================
#
# ======================================================
echo "please add usb cable";
echo "Are you ok ? [ ENTER ]"
read -p "Hit enter: "
lsusb > lsusb_second.txt ;

# ======================================================
#
# ======================================================
RESULT_DIFF=diff -u lsusb_first.txt lsusb_second.txt | grep ^+ | grep -v ^+++ | sed s/^+//;
echo $RESULT_DIFF
#+Bus 001 Device 004: ID 1774:1001 Strawberry Linux Co.,Ltd. Hygrometer/Thermometer

# ======================================================
#
# ======================================================
cat RESULT_DIFF | awk -F'[ ]' '{print $6}'
cat RESULT_DIFF | awk -F'[ ]' '{print $7}'
cat RESULT_DIFF | awk -F'[ ]' '{print $8}'
cat RESULT_DIFF | awk -F'[ ]' '{print $9}'

#hidraw0

# Ubuntu日本語フォーラム / USBへのアクセス権限について https://forums.ubuntulinux.jp/viewtopic.php?id=7491
#sudo vi /etc/udev/rules.d/50-udev.rules
#KERNEL=="ttyACM*", ATTRS{idVendor}=="1774", ATTRS{idProduct}=="1001", GROUP="$USER", MODE="0666"
````
Slim-Skeletonを使ってslim4.0を構築しするだけ


個人的な習作に関するメモ

## 前提

- windows10（hyper-v有効）
  - docker install済み
  - composer install済み

## step1 とりあえずプロジェクト構築

https://www.slimframework.com/

> `php composer.phar create-project slim/slim-skeleton:dev-master [my-app-name]`

まずはこれを動かしてプロジェクトを作りたい。このままだと使えないので

> `composer create-project slim/slim-skeleton slim-auth`

と変更して実行。win内のphpが8系だったので怒られた。（何故か7系縛り）

適当にdockerで環境を立ち上げる

> `docker run --mount type=bind,src=${PWD},dst=/var/www --name php --rm -it php:7 bash`

これだとcomposerが動かないので雑に https://getcomposer.org/download/ これを実行し、composerが動く環境を用意。

コンテナ内部で下記実行。途中色々ないと怒られたのでついでにそれも入れる。

```
cd /var/www
apt-get update
apt-get install -y git zip unzip
php composer.phar create-project slim/slim-skeleton slim-auth
```

で、OK。スマートにやる方法は絶対あるけど、ググルのめんどいのでとりあえずこんな感じで。

exitで抜けて作業終了。

## step2 slim動かす

作ったディレクトリにdocker-compose.ymlがあるので、それを少し改造する。

最新のslim4.7ではphp8で動くっぽいので、php8にする。とりあえずそれだけ。

`docker-compose up -d` すれば `http://localhost:8080/`にアクセスできるようになる。

これでOK。

## step3 ディレクトリデザインを見ていく。

ADRパターン (Action Domain Responder) というのに沿って作られてるらしい。MVCを触ることが多かったので少し困惑したが、慣れればそんなに問題じゃない。

とりあえず、ぱっと見た感じ

ドメイン層はRepositoryのInterfaceとか、そこから取得できるデータのEntityクラスを持っている。
インフラストラクチャ層では、ドメイン層で持つInterfaceの実装をやってる。
アプリケーション層は...めっちゃ広い。その他。みたいな感じ。

個人的に、Interfaceクラスの末尾にInterfaceと書いてないのが混乱の元だったので、そこは後でどうにかしたい。

## 総括

laravel以外のフレームワークを選ぶとした何がいいかなー、特に深い思い入れはないけどDIとかrouteの設定は似てるやつがいいなと思って見つけたのがslim。

せっかくだからメモ的にQiitaにまとめようと思ったのがこの記事を書いたきっかけです。

Windowsでphpを使っていてslimを使おうとしているｎ人の開発者の役に立てば幸いです。

では。

end
yukicoder contest 291 参戦記

# yukicoder contest 291 参戦記

## [A 1476 esreveR dna esreveR](https://yukicoder.me/problems/no/1476)

a<sub>i,i</sub> と a<sub>N-i,N-i</sub> の組み合わせ、それぞれが<sub>4</sub>C<sub>2</sub>で6パターンとなり、それぞれの組み合わせは互いに影響しあわないので、6<sup>⌊N/2⌋</sup>が答えとなる.

```python
m = 998244353

N = int(input())

print(pow(6, N // 2, m))
```
[SwiftUI]functionを勉強し直してみた！

## はじめに
今回はとある課題でfunctionを使用する上でつまづく所が多かった為、この機会に学び直す事にしたのでまとめてみました！

## 環境
・ /macOS Big Sur 11.3
・ SwiftUI : 2.0
・ Xcode : 12.4

## functionの基本的な使用
Swiftで関数を使用する場合主に”関数名”、”仮引数”、”型”の指定をして使用します。

```swift
   func 関数名 (仮引数: 型) -> (型) {
        コード.....
    }
```
とこんな感じがオーソドックスかと。
また関数名、仮引数名ともローワーキャメルケースで書くことが推奨されています。
[（キャメルケースについてはコチラをご覧ください。）](https://wa3.i-3-i.info/word13954.html)

仮数名や型はオプションなので省略することも可能です。つまり最小の実装は

```swift
   func 関数名() {
        コード.....
    }
```
となります。

では早速SwiftUIで使用してみましょう。
![スクリーンショット 2021-04-17 15.46.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/a450f34a-4612-5a29-e322-7d011886e1fb.jpeg)
エラーが出ました！これはSwiftUIではViewをコードで生成させる為、Viewを記載する箇所がありますが、その中でfunncは使用しないで下さいね、と言うエラーです。
![スクリーンショット 2021-04-17 15.47.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/c80e1970-f5e4-2fce-38e5-5cf3bb972bec.jpeg)
なのでこのようにViewの外に書いてあげればOK！

続いてfunctionを使用してみましょう。

```swift
   @State var showHogeText = false
 func hogehoge () {
        self.showHogeText.toggle()
    }
```

```swift
   Button(action: {
                hogehoge()
            }) {
                Text("hogehogeボタン")
            }
            Text(showHogeText ? "ボタンを押した後" : "ボタンを押す前")
                .foregroundColor(showHogeText ? .red : .black)
        }
    }
```
![y1zsi-5coim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/4ec4d813-72b3-7b81-2e2d-a01799c019da.gif)
上記のコードを実行するとGifのようなViewを生成することができます。


## 値を返すreturn
上記のように値を返さない関数は仮引数や型を省略するか -> ()とするか、-> voidとします。
ここでは値を返す事も試してみます。

```swift
    func num (n: Int) -> Int {
        total += n
        return Int(total)
    }
```
この様値を返す時はreturnを使用します。
そして上記の関数の使用方法は

```swift
  struct funcTtaining: View {
    @State var total = 0
    
    var body: some View {
        VStack{
            Button(action: {
                total = num(n: 1)
            }) {
                Text("ボタン")
            }
            Text("\(String(total))")
        }
    }
}
```

で使用できます。
ここではボタンを押すとnum関数の仮引数nに１が指定されているのでその1が関数内でtotalに足されて、足されたtotalがreturnで返され、button内のactionでtotalに渡される流れとなります。
![553ce-t3aks.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/4a3858e8-cfba-ddf9-428c-0c04076de075.gif)

## まとめ
functionの基本的な使い方を整理してみました。
この記事は引き続きfunctionに関して気づいた点があれば随時追記していこうと思います。
plunkerでthreebsp

#概要

plunkerでthreebspやってみた。
subtract使ってみた。

#参考にしたページ。

https://qiita.com/ittakun/items/91c26ead7295959d8d19

#写真

![subtract.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8ca4ee85-4ab3-f01d-e327-9e53bc855bdf.jpeg)


#サンプルコード

```

var renderer, 
	scene, 
	camera, 
	light;
document.addEventListener("DOMContentLoaded", setTimeout(function() {
	renderer = new THREE.WebGLRenderer({
		antialias: true
	});
	renderer.setSize(window.innerWidth, window.innerHeight);
	document.getElementById('viewport').appendChild(renderer.domElement);
	scene = new THREE.Scene();
	light = new THREE.DirectionalLight(0xffffff);
	light.position.set(1, 1, 1).normalize();
	scene.add(light);
	camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
	camera.position.set(5, 5, 15);
	camera.lookAt(scene.position);
	scene.add(camera);
	(function() {
		var start_time = (new Date()).getTime();
		var cube_geometry = new THREE.CubeGeometry(3, 3, 3);
		var cube_mesh = new THREE.Mesh(cube_geometry);
		cube_mesh.position.x = -7;
		var start, 
			stop;
		start = Date.now();
		p = {};
		var cube_bsp = new ThreeBSP(cube_mesh, {
			timeout: 2000, 
			progress: function(c, t) {
		  		percent = Math.round(c / t * 100)
		  		if (p['P' + percent] === undefined) 
				{
					p['P' + percent] = true;
					console.log(percent + "%");
	  		}
			}
		});
		stop = Date.now();
		console.log("Elapsed(build cube): ", stop - start);
		var sphere_geometry = new THREE.SphereGeometry(1.8, 32, 32);
		var sphere_mesh = new THREE.Mesh(sphere_geometry);
		sphere_mesh.position.x = -7;
		start = Date.now();
		var sphere_bsp = new ThreeBSP(sphere_mesh, {
			timeout: 3000
		});
		stop = Date.now();
		console.log("Elapsed(build sphere): ", stop - start);
		start = Date.now();
		var subtract_bsp = cube_bsp.subtract(sphere_bsp);
		stop = Date.now();
		console.log("Elapsed(cube - sphere): ", stop - start);
		start = Date.now();
		var result = subtract_bsp.toMesh(new THREE.MeshLambertMaterial({ 
			shading: THREE.SmoothShading, 
			map: THREE.ImageUtils.loadTexture('texture.png') 
		}));
		stop = Date.now();
		console.log("Elapsed(toMesh): ", stop - start);
		result.geometry.computeVertexNormals();
		scene.add(result);
		console.log('Example 1: ' + ((new Date()).getTime() - start_time) + 'ms');
	})();

	(function render() {
		requestAnimationFrame(render);
		renderer.render(scene, camera);
	})();
}, 1000))





```

#成果物

https://embed.plnkr.co/plunk/uxeJkY5Ax56fHrFR

以上。
MVCモデルについて

#はじめに
この記事では、MVCモデルについて簡単にまとめました。
⚠️当方初学のため認識違いがある可能性大です
誤りを見つけた際はコメントにて指摘していただけると幸いです🙇‍♀️🙇‍♂️


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

- [Wikipedia](https://ja.wikipedia.org/wiki/Model_View_Controller)
- [DeveloperApple] (https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html)


#MVCモデルとは
MVCモデルとは、役割ごとにModel, View, Controllerに分割してコーディングを行うモデル、アーキテクチャの一種。
とても多く利用されている。
iOSアプリで利用されるMVCは厳密にはCocoa MVCと呼ぶ。
![Controller.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/3e7c2c5e-0d06-b3e2-96c9-3d28b063cd88.png)
(https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html から引用)
Model : ソフトウェアを処理
View : 表示
Controller : 入力伝達
User action (View → Controller) : ユーザー操作
Update(Controller → View) : 画面の切り替え（更新）
Notify(Model → Controller) : 通知
Update(Controller → Model) : 情報取得の依頼


#Model
固有のデータをカプセル化し、そのデータを操作および処理するロジックと計算を定義。
<例>
`固有のデータ → キャラクター（レベル50 攻撃力500）
操作 → 歩く、攻撃
処理 → レベル+1↑ 攻撃力+10↑`


#View
ユーザーが見る/操作する画面を表示。
ユーザー操作を受け、Controllerを介しModelから操作に対するアクションを受け、画面を更新。
<例>
`ユーザーが見る/操作する画面 → カウントアップボタン（１））
ユーザー操作 → ボタンをタップ
画面更新 → カウントアップ（２）`


#Controller
ModelとViewの仲介役。
Viewのリクエストを受け必要な情報をModelに要求。
Modelから情報を受け取りViewへ渡す。
その他アプリのセットアップ等を管理。
<例>
`Viewのリクエスト → 姉から唐揚げ食べたいと言われる
Modelへ要求 → 母に姉がからあげ食べたいと伝える
Modelから情報を受け取り → 母から唐揚げを受け取る
Viewへ渡す → 姉へ唐揚げを渡す`
Flaskを使用したTwitter ログイン連携メモ

* Flaskを使用したTwitterログイン連携についてメモする。
  * [Google連携](https://qiita.com/KWS_0901/items/28066892d0811e571796)や[Facebook連携](https://qiita.com/KWS_0901/items/e9b0f81464370ffed3cd)を試したもののTwitter版

## 大まかな処理の流れ

1. <u>**リクエストトークンを取得する。**</u>※GoogleやFacebookなどと異なる点。

2. リクエストトークンを指定してTwitterへ認可リクエスト(Authorization Request)を行う。

3. ユーザー認証/同意を行い、認可レスポンスを受け取る。

4. 認可レスポンスを使ってトークンリクエストを行う。

   

## 事前準備

* [Twitterデベロッパーコンソール](https://developer.twitter.com/en/portal/dashboard)からアプリケーションを登録する。
  * API Key and Secretの取得する。
  * コールバック(リダイレクト)URIの設定する。
    * 今回はhttp://localhost:5000/callback を設定する。




## 実装

* アクセストークンを取得するまでのコード

```python
from requests_oauthlib import OAuth1Session
from flask import Flask, jsonify, request, redirect
import urllib.parse as parse

# App Info
api_key = "<YOUR API KEY>"
api_secret = "<YOUR API SECRET>"

# Twitter Endpoint
twitter_base_url = 'https://api.twitter.com'
authorization_endpoint = twitter_base_url + '/oauth/authenticate'
request_token_endpoint = twitter_base_url + '/oauth/request_token'
token_endpoint = twitter_base_url + '/oauth/access_token'

app = Flask(__name__)


@app.route("/login")
def login():
    # 1.リクエストトークンを取得する。
    # (Step 1: Obtaining a request token:https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter)
    twitter = OAuth1Session(api_key, api_secret)
    oauth_callback = request.args.get('oauth_callback')
    res = twitter.post(request_token_endpoint, params={
        'oauth_callback': oauth_callback})
    request_token = dict(parse.parse_qsl(res.content.decode("utf-8")))
    oauth_token = request_token['oauth_token']
	
    # 2.リクエストトークンを指定してTwitterへ認可リクエスト(Authorization Request)を行う。
    # (Step 2: Redirecting the user:https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter#tab2)
    return redirect(authorization_endpoint+'?{}'.format(parse.urlencode({
        'oauth_token': oauth_token
    })))


@app.route("/callback")
def callback():
    # 3.ユーザー認証/同意を行い、認可レスポンスを受け取る。
    oauth_verifier = request.args.get('oauth_verifier')
    oauth_token = request.args.get('oauth_token')

    # 4.認可レスポンスを使ってトークンリクエストを行う。
    # (Step 3: Converting the request token to an access token:https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter#tab3)
    twitter = OAuth1Session(
        api_key,
        api_secret,
        oauth_token
    )

    res = twitter.post(
        token_endpoint,
        params={'oauth_verifier': oauth_verifier}
    )

    access_token = dict(parse.parse_qsl(res.content.decode("utf-8")))

    return jsonify(access_token)


if __name__ == "__main__":
    app.run(debug=True)

```



## 参考情報

* [3-legged authorization](https://developer.twitter.com/ja/docs/basics/authentication/overview/3-legged-oauth)
* [Log in with Twitter](https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter)
* [[Python] OAuth認証でTwitter連携/ログインを実装する](https://qiita.com/mikan3rd/items/686e4978f9e1111628e9)
メールのプロトコル (SMTP, POP, IMAP)

#はじめに
メールの送受信に使用しているプロトコルにはいくつかありますが、その中でも代表的なSMTP, POP, IMAPの挙動について簡単にまとめました。

##メール関係のプロトコル

|プロトコル|概要|
|:--:|:--:|
|SMTP|Simple Mail Transfer Protocol。利用者がメールを送信する時やサーバ間でメールを送受信するときに使用される。|
|POP|Post Office Protocol。メールサーバのメールボックスからメールを取り出すときに使用される。|
|IMAP|Internet Message Acess Protocol。メールサーバーのメールボックスからメールを取り出す時に使用される。POPとは違い、サーバー上のメールボックスから、必要なものだけを選択して受信することができる。|

##各プロトコルの挙動
![protocol.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/3f7ec5ec-d892-5e70-266d-3ebdceb770fa.png)



###SMTPプロトコル
メールを相手のメールサーバーまで届ける仕組みをSMTPという。__メールサーバーまでしかメールを渡さないため、相手のメールソフトまで届けているわけではない。__

###POPプロトコル
電子メールはスマホやパソコンに自動的に送られるわけではない。メールソフトを立ち上げていれば__何もしなくてもメールが届いているように感じるが、実際はメールソフトがメールサーバーにアクセスしてダウンロードしている。__このメールサーバーからメールをとってきて、端末側で管理する仕組みをPOPという。

一般的にメールソフトがメールをダウンロードした後は__メールサーバーのデータは削除される。__受信した端末にデータが保存される形式なので、複数台でメールを閲覧する場合には向かない。

###IMAPプロトコル
POPと同じくメールを取り込むための手段であるが、__ダウンロードするのはメールのコピーであり、メール本体はサーバーに残ったままで、サーバーが管理する。__メールサーバーにメールを保存しておくため、__複数の端末からメールサーバーにアクセスして、メールを読むことができる。__

POPのようにメールを全てダウンロードする必要がないため、ネットワークにかかる負荷を軽減できる。デメリットとしては、メールサーバーにデータが残り続けるため、サーバー側の容量次第では、すぐにメールボックスが満杯になってしまう。

##メール受信のPOPとIMAPの違い
⭐️ POPはメールサーバーから端末へ全てのメールを渡す！メールサーバーのデータは消える！
⭐️ IMAPはメールサーバーから必要なメールのみコピーで渡す！メールサーバーのデータは消えない！
プログラミングの初歩(4)

みなさん、こんにちわ

私はSE歴5年の、ごくごく一般的なサラリーマンです。
仕事を始めてからＩＴ系の勉強を始めましたし、IT業界に入ってからすぐにプログラミングができるようになった、いわゆる才能があるわけでもありません。

それでも今、多少プログラミングのことがわかりましたし、それで仕事もいただけています。
この知識が誰かの役に立つと思って、この記事を書くことにしました。


プログラミングの初歩(3)の続きです。

<br>
<br>

前回は、言語のインストール、例としてpythonのインストールと、
実際に動いているかのテストとして、printを実行してみました。

<br>

今回は、毎回コマンドプロンプトに向かってやりたいことを入力するのではなく、
ファイルに書いておいて、その実行ファイルから同じようにプログラムを実行できるようにします。

<br>

とは言っても、pythonであればそこまで難しくありませんし、ほかの言語でもそこまで難しいものではないはずです。
(例外として、『コンパイル』という作業が必要な言語があります。)

<br>
<br>

では、何をすればいいのかというと、ファイルに実行したいこと(前回の例ならprint('ABC'))を記入して、
ファイルの形式を実行ファイルの形式で保存すればいいだけです。

<br>
<br>
<br>
詳しく説明しますね。

ます、『ファイルに実行したいことを記入する』というのは、そのままファイルに書くだけです。
じゃあ、どんなファイル(windowsならワードとかエクセルとか)でもいいのかというと、
それは違うというか、余計な作業が必要になる可能性があります。

<br>
プログラムの実行ファイルの記入は、ただのテキストファイル(～～～.txt)に行います。
ただのテキストファイルの開くには
「windowsメニュー」→「windows アクセサリ」→「メモ帳」
を実行してください。
そうです。ただのメモ帳です。

このメモ帳を保存すると、基本的に入力した文字の情報のみが保存されています。
実行ファイルには、ワードのように書式を変更したり、エクセルのようにセルの情報は必要なく、
実行したいことだけ記憶されていればいいので、メモ帳で十分ですね。

<br>
(記事の最後に、メモ帳以外のエディタについて少し書きました)
<br>

（３）の記事でも触れていますが、
言語によってはコマンドプロンプト上からでは実行できず、実行ファイルにしないと実行できないものもあります。

言語の種類と特徴、選ぶ基準みたいなものがわかりやすくまとめられている記事があれば、
リンクをこちらの記事に追加しておこうと思います。

<br>
<br>
各言語の詳細な記載ルール、記載方法などは(いつもながら)ここでは詳しく書きませんが、
大まかな流れとして

・実行前の宣言(あったりなかったり)
・実行したいこと


の順番に書きます。
実行したいことが長くなってくると、

* 実行前の宣言(たいていある)
* 実行したいことのまとめ
* 実行したいことの詳細１
* 実行したいことの詳細２
* 実行したいことの詳細３
<br>
  ：

のように、やりたいことを分割する書き方をします。
<br>
例えば、実行したいことが「カップラーメンを食べる」だとすると、

* カップラーメンを開ける
* かやく、スープを入れる
* お湯を入れる
* 書かれている時間待つ
* 食べる

の5ステップです。
(ふた閉めろ、スープが2種類だったら？などのツッコミはなしで)

これは『実行したいこと』に5行で書いても見やすいですが、
実行したいことが「本格手作りラーメンを作って食べる」になると話が変わってきます。
麺を作ることだけを考えても

* 小麦粉、塩、水、その他を混ぜる
* 練る
* 寝かせる
* 成形する
* ゆでる
<br>
(すいません、製麺の知識はないので詳しくは知りません... (-_-;) )

というステップが必要で、スープや具材、仕上げなどにも同じくらいのステップがあるとすると、
全部で20ステップになり、先ほどのカップラーメンの4倍以上の長さになります。
これはさすがにスクリプトが長くなり、読みづらい、分かりづらいことになります。

プログラムの書き方については、別途まとめようと思いますが、
ダラダラと書くのではなくて、分かりやすいまとまりに分けて書く、ということだけ覚えておいていただきたいです。

かなり話が脱線してしましました。
今回の話題はあまり内容が長くなる予定ではなかったので、むしろ良かったかも知れないですね(^_^.)

<br>
<br>
<br>

※テキストエディタについて

メモ帳だと使いづらい、見づらい、ということであれば、
ネットで「テキストエディタ  おすすめ」などで検索して、
自分に合っているものをインストールしてください。
Qiita内にもおすすめエディタのまとめなどがあると思います。
『テキストエディタ』となっているものであれば、メモ帳と同じような機能のものになっているはずです。
<br>
<br>
テキストエディタとは別に、開発専用のエディタなどをインストールすると効率的に作業ができます。
このあたりもQiita内にまとめられているかと思いますが、
まだパソコンに慣れていない方はインストール自体が難しいということもあると思うので、
パソコンに慣れてからインストールでも問題ないと思います。

個人的に今使っているのは、
テキストエディタは「サクラエディタ」
プログラムの編集は「VS CODE」
というツールを使用しています。

どちらもIT業界では有名なものだと思うので、検索すればインストール方法はたくさん記事になっているはずです。

<br>
<br>

もし、これ以外にもおすすめのエディタなどがあれば教えてほしいです！
まだまだ私も知らないことのほうが多いので(;^ω^)

<br>
この記事に関して、ご意見や相談があればぜひぜひコメントをお寄せください。

では次に続きます。
altairでとあるアイドルグループのメンバー在籍期間のチャート化してみた

# 記事の内容
数年前から転校少女*というアイドルグループを応援しているのですが、メンバーの入れ替わりが激しく誰がいつ在籍していたのか分からなくなったので「altair」というライブラリを使って可視化してみるという内容です。

#altairのインストール
pipでインストールします

~~~
pip install altair
~~~

#準備データ
~~~ tenkou.csv
No,Member,Start,End,Color,Color Name
1,松井さやか,2014/11/01,2021/05/01,#ff6666,red
2,塩川莉世,2014/11/01,2021/05/01,#ff99cc,pink
3,岡田夢以,2014/11/01,2019/11/16,#66ccff,blue
4,栗田恵美,2014/11/01,2018/04/28,#66ff66,green
5,松本香穂,2014/11/01,2018/04/28,#ffff66,yellow
6,古森結衣,2017/01/28,2018/04/28,#FFA500,orange
7,渚まお,2017/01/28,2019/04/30,#DFA0D2,purple
8,千葉妃理,2017/06/01,2018/07/26,#0000ff,black
9,寺田葵,2018/09/16,2020/12/26,#00A474,black
10,小西杏優,2019/08/25,2020/01/12,#FFA533,black
11,上原わかな,2019/08/25,2020/04/23,#800080,black
12,小倉月奏,2019/08/25,2021/04/16,#FFFF00,black
13,佐藤かれん,2020/11/21,2021/05/01,#800088,black
14,成島有咲,2020/11/21,2021/05/01,#66ddff,black
15,佐々木美紅,2020/11/21,2021/05/01,#FFA566,black
~~~
データの内容はNo（ソート用）、メンバーの名前、在籍期間を表すstartとend、グラフの色を設定するためのColor、Color Nameを用意しました。
まだ在籍しているメンバーのendはとりあえずで「2021/05/01」を設定しています。

#コード１
早速コードを書いてみました

~~~ chart.py
import pandas as pd
import altair as alt

df = pd.read_csv("tenkou.csv")

df["Start"] = pd.to_datetime(df["Start"])
df["End"] = pd.to_datetime(df["End"])

chart = alt.Chart(df).mark_bar().encode(
    x='Start',
    x2='End',
    y=alt.Y('Member',sort=list(df.sort_values(['No']))),
    color='Color'
    ).properties(
        width=1500,
        height=500
    ).interactive()

chart.show()
~~~

## 実行結果
画像なので分からないのですが、チャートの部分は横スクロールが出来るようになっています。
横スクロールが出来るようになってはいますが、何も設定していないと「properties」の「width」で指定した幅でデータが表示されるように横軸の間隔が調整されるみたいです。

![chart1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476876/c903027e-c8af-0a9b-0c7e-670b9d2f3b5e.png)

## 問題と原因
用意したデータの「Color」にはメンバーの担当カラーを設定していたのですが、グラフの色が用意した色になっていない。

調べたところ、以下の部分は色を指定するのではなく、色分けするデータ群に対するラベルの意味合いみたいです。

~~~
    color='Color'
~~~

例えば、一期生、二期生・・というデータを加えて、それぞれ色分けするような場合に使えます。
![chart3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476876/f15aa723-c743-5f6d-c14f-2f846d504732.png)


色はaltairが勝手に設定するみたいで、このやり方だと自分で色の設定は出来ないっぽい。
色の設定は別でやる必要あり。


#コード２

~~~ chart2.py
import pandas as pd
import altair as alt

df = pd.read_csv("tenkou.csv")

df["Start"] = pd.to_datetime(df["Start"])
df["End"] = pd.to_datetime(df["End"])

chart = alt.Chart(df).mark_bar(color='Red').encode(
    x='Start',
    x2='End',
    y=alt.Y('Member',sort=list(df.sort_values(['No']))),
    ).properties(
        width=1500,
        height=500
    ).interactive()

chart.show()
~~~

変更点としては、mark_barに色を設定したのと、colorの設定を消しただけ

## 実行結果
![chart2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476876/9e1a232a-0ef0-f460-1f46-d56f03317c06.png)

設定した色に変更されました。
今回は赤だけを設定したのですが、メンバー毎に色を設定したくてリストで担当カラーを渡してみましたがエラーとなり失敗しました。
現状、自分で好きな色に設定することは難しそう

# 感想
割と簡単かつ綺麗に描画された点は良いなと思いました。
今後使っていく場合、ドキュメントが若干分かり辛いのと、情報が少ないので細かい使い方を調べるのには少し苦労しそう。
あとは、応援してるグループのメンバー在籍期間を可視化すると改めて入れ替わりが激しいなと思い知った。
改行コードを変数へ入れる（POSIX）

こんにちは。
改行、タブなどのコードを変数へ入れました[^1]。シェルスクリプトなどで使う目的です。

```lf.sh
#!/bin/sh
LF=$(printf '\n_');LF=${LF%_}
TAB=$(printf '\t')
ESC=$(printf '\033')
```

##### Bash #####
Bash ならばシンプルな構文を持っています：
```bash
LF=$'\n'
TAB=$'\t'
ESC=$'\e'
```


[^1]: 参考：「[シェルの文字列変数に改行を書き入れる方法](https://qiita.com/kkdd/items/6b0534b3b64639ac3e25)」
Postmanを使用してRailsAPIの確認(CRUD)

##はじめに
RailsでCRUD機能を持つAPIを作成したので今回は、postmanで確認する方法を重点に置いて自分用メモとしてまとめていこうと思います!
※API作成手順は以下の記事を参考にさせて頂きました。
[Railsで超簡単API](https://qiita.com/k-penguin-sato/items/adba7a1a1ecc3582a9c9)
[Railsガイド](https://railsguides.jp/api_app.html)


##postman初期設定
1,「new」を選択し、「collection」を作成。　
![スクリーンショット 2021-04-17 18.06.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/a8f4b4bf-5ece-087f-7d5d-647b123ad9b8.png)
2,「new」で「request」を作成。
Requestで「name」(任意)を入力し、先ほど作成した「collection」を選択し、「save to create」で作成。
![スクリーンショット 2021-04-17 18.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/5ed33194-6e84-d054-2c4a-93ad7ca3b49c.png)

これで下準備は完了し、次からレスポンスの確認にはいる。
##GETリクエスト
投稿を全て取得する方法
画面は以下のような感じ
![スクリーンショット 2021-04-17 18.17.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/f32d5bb9-4384-3fcb-587d-08e34aaa4725.png)
1,「GET」を選択し、URLを入力する。
今回は、(http://localhost:3000/api/v1/posts) を入力する。
※rails routesで確認する。
2,rails server起動
3,「save」して「send」を実行すると、以下のようにJSON形式で値を取得することができる。
![スクリーンショット 2021-04-17 18.25.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/07c0f537-1084-ec86-6de8-f03534174a95.png)
※rails sしていないと以下の画面が表示される。
![スクリーンショット 2021-04-17 18.21.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/78972018-23a3-b4b8-850f-4387702c7df9.png)

##POSTリクエスト
1,「POST」を選択し、同じくURLを入力。
2,「body」→「raw」→「JSON」をそれぞれ選択する。
3,JSON形式で値を入力する。
![スクリーンショット 2021-04-17 18.33.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/aedb3b15-dd79-6f9f-dfef-90fb9006506f.png)
4,「save」→「Send」
5,getに戻り、データが追加されていることが確認できる。
![スクリーンショット 2021-04-17 18.36.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/50b27465-ddb8-38a6-b9f7-4b2e7e24b8cf.png)
##UPDATEリクエスト

1,「PUT」を選択し、同じくURLを入力。
2,paramsで編集する値を指定。
![スクリーンショット 2021-04-17 18.49.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/a261e688-c190-f833-0313-58ccce6da3f0.png)
3,「body」→「raw」→「JSON」それぞれ選択し、編集したいデータを入力する。
![スクリーンショット 2021-04-17 18.50.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/55e2e2d7-ca2f-2643-31bd-fe10099e0e14.png)
4,「send」を実行すると、上書きされる。
##DELETEリクエスト
1,「DELETE」を選択し、同じくURLを入力。
2,paramsで削除する値を指定し、「send」で実行。
3,getでtitle5が消えていることが確認できる。
![スクリーンショット 2021-04-17 18.54.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/c31e56fa-3f84-a762-17da-6c8a0842cd3e.png)


##まとめ
・簡単ではありましたが、postmanを使用し、CRUDのリクエストを確認していきました。
・今後もっとうまく活用できるようにしていきたいと思います。

最後まで読んでいただきありがとうございました！
少しでも参考になれば幸いです。
AWS Lambda内Lambdaの呼び出しで Invalid type for parameter Payload

# Invalid type for parameter Payload

AWS Lambda内でLambdaを非同期で呼び出そうとして
以下のような呼び出しでエラー発生。

```
directive = {
   'target': 'hogehoge',
   'set': 'mogemoge'
}

response = boto3.client('lambda').invoke(
   FunctionName='hogehoge-actions-reportstate',
   InvocationType='Event',
   Payload=directive
)
```

原因はPayloadで渡す変数「directive」をdictで渡していたこと。json.dumps()で変換後に渡すことで解決。