OmniAICreator/Qiita-1.07M huggingface dataset:
lambdaでAPI Gateway経由のquerystringを取得する(Python)

# はじめに
AWS Lambdaを初めて触ってみました。
QueryStringを取得して、レスポンスを返すことがあっという間にできたのでメモです。

# 環境
最初は使っているWindowsにすでにインストールされているバージョンに合わせるために`Python3.6`を使用しました。
ですが、Lambdaだとローカルでテストが不要なのでバージョンを合わせる必要はありませんでした。
AWS上で現時点でサポートされる最新のバージョンを使っていいと思います。
(処理がシンプルすぎるので当たり前ですが、`Python 3.8`で作り直してもうまく動きました。)

# まとめ
`event['queryStringParameters']['name']` でできます。

# 構築
## AWS アカウント取得
なんと、ほぼ触ったことがなかったのでアカウント作成からやりました。

## 課金時の通知
課金されたら知りたいので、予算を登録して、$1で通知が来るように設定しました。
課金されてないので、通知が来るようになっているのかどうかよくわかりません。

## Lambda の作成
サービスからLambdaを開きます。
お試しなのでサクッと作成します。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/b7c44b6a-9589-7a02-c0ef-048820025062.png)

`harowa` できました。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/409d5092-b387-e4fc-bd88-d84e272d1fb9.png)

## API Gateway の作成
`トリガーを追加`をクリックして、さささーっと作ります。
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/03408bf0-83be-8334-8e33-cd8c3f0baf66.png)

`REST API`にすると、`POST,PATCH,DELETE`とかを受け取れるんですかね。
やったことないのでわかりません！

出来ました。
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/1c1f4e38-193f-2cc0-d311-675437130613.png)

## もうインターネット上に乗ってることを確認する
ここで一度API GatewayとLambdaが連携できてることを実感しましょう。
`API Gateway`の`APIエンドポイント`にあるURLをクリックします。
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/b382f1d3-646e-51fd-f0fe-b212cdfacb8b.png)
どこがインターネット上に公開しちゃいけない情報なのかわからなかったので、よくわかんない情報は塗りつぶしました。

ブラウザ上に`"Hello from Lambda!"`って表示されたかと思います。
はやーって感じですね。

## QueryStringを出力するように変更
`Lambda`を開きます。
すると、下に関数のエディターが開きます。
![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369361/79d7aae2-5b03-b3ad-5b56-44d643056634.png)

ここで以下のようにソースをいじります。

```python:querystring_sample
import json

def lambda_handler(event, context):
    # TODO implemen
    name = event['queryStringParameters']['name']
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!' + name)
    }
```

変更したら、`Save`！！
以下、変更点です。

* `name = event['queryStringParameters']['name']`を追加
* `'body':～`のところに`+ name`を追加しています。

`event`の構造については、こちらのページを参考にしました。
[他のサービスで AWS Lambda を使用する](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-services.html)

あとは、API GatewayのAPIエンドポイントのURLの末尾に`?name=wakoit`と追加してアクセスすればOK！
ブラウザに`"Hello from Lambda!wakoit"`と表示されました！

# その他
querystringを指定されなかった場合に、Internal Server Errorになってしまうので、実際に使う場合は例外処理などをきちんと入れる必要がありますね。

Lambdaのfunctionのテストを何も考えずに作るとエラーで機能しなくなるので、querystringを渡すようなテストを作る等の対応が必要そうです。
(そこまで試していません)

# まとめ
サーバーレス楽しいですね。
インフラエンジニアとしては、ちょっと怖いですけど。
データベースプロキシの機能を使って、データベースに書き込むこともできそうなので、お手軽にAPIサーバーを建てることができそうですごいですね！

悪意のあるアクセスがいっぱい来て、Lambdaの無料枠消化されたら怖いのでfunctionは削除しましたとさ＾＾
Webデザインの基礎知識

## この内容について
この内容は、Webデザインの基礎的な知識をまとめたものです。
これからWebデザインを勉強するにあたり、最初に読んで活用いただければ幸いです(^^)

## デザインはアートとは違う
デザインは、アートとは違います。
デザインは、客観的に実用的で、人に情報や目的を伝えます。
アートは、主観的で、万人に理解されなくても成り立ちます。

> Design is not just what it looks like and feels like. Design is how it works.
スティーブ・ジョブズ

デザインはどう見えるかよりも、どう機能するかが大事です。

## Webデザインとは
パソコンやスマホなどで表示されるもののデザインをすること。
Webデザインは、印象と機能の大きく2つの組み合わせです。

### 印象に影響を与えるもの

- 色
- フォント
- 文字サイズ
- 画像
- 装飾

### 機能に影響を与えるもの

- レイアウト
- 情報の整理
- 情報の配置方法
- アニメーション
- ナビゲーション

これらを意識することでより良いWebデザインが可能です。
しかし、これらの項目を意識しろと言われてもピンとこないので、
後述するWebデザインの原則を使うとより明確にわかるかと思います。

## Webデザインと紙デザインの違い
WebデザインはもちろんWeb上のコンテンツのものをデザインすることで、
紙デザインは紙で印刷するものをデザインすることですが、その他の違いもあります。

|| Webデザイン | 紙デザイン |
|:--|:--|:--|
| 特徴 | パソコンやスマホなどで見え方が変化する中でデザインをする | A4やB5などの決められたサイズの中でデザインをする |
| 色 | RGB | CMYK |
| 単位 | 距離単位：px ( em・%・rem・vw・vh ) 文字単位：px ( em・%・rem・vw・vh ) | 距離単位：mm 文字単位：pt・級 |
| 考え方 | 全体+ファーストビューの見せ方と運用を見越したデザインを考える | 全体のまとまりを考えた見せ方と完成後は修正できないことを見越したデザインを考える |

## Webデザインの原則
### 近接
同じ属性のものをグループ化し、適切な余白をとります。
![Design_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473780/2ea24993-2583-d667-7fe5-852877c69546.png)

### 整列
近接でグループ化したものを、縦または横に揃えて並べます。
![Design_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473780/0b894619-66e5-3487-0b31-42dc17f691f2.png)

### 強弱
優先度に応じて、サイズや色でメリハリをつけます。
![Design_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473780/c603bb22-46cd-b541-ec91-b3fa71a61812.png)

### 反復
同一のモチーフを繰り返し使うことで、全体に一貫性を持たせます。
![Design_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473780/83051cf9-0c48-eaab-501e-82a6bdc9b968.png)

## Webデザイナーが使うツール
Webデザイナーは、デザインツールを使います。
使うツールは、主に下記のものです。

- [Adobe Photoshop](https://www.adobe.com/jp/products/photoshop.html?promoid=PC1PQQ5T&mv=other)
- [Adobe Illustrator](https://www.adobe.com/jp/products/illustrator.html?promoid=PGRQQLFS&mv=other)
- [Adobe XD](https://www.adobe.com/jp/products/xd.html?promoid=PYPVQ3HN&mv=other)

Photoshopは、画像の編集から文字入れレイアウトまで一貫して行えます。
Illustratorは、イラストの作成やロゴの作成に向いています。
XDは、Webサイトやモバイルアプリの試作的な段階でのデザインの作成に向いています。
ちゃんと使うにはどれも有料で、Photoshopは980円/月(フォトプラン)、Illustratorは2480円/月(単品)、XDは1180円/月(単品)となっています。
Adobe製品全て使えるコンプリートプランが5680円/月となっています。 ※ 学割あり 1980円/月

その他にも [Sketch](https://www.sketch.com/) というXDに似たツールを使ったりする方もいます。(値段は99ドル)

## Webデザイナーの役割
Webデザイナーは、クライアントが実現したい目標をWebデザインを通じて実現させることが役割です。

具体的には、もしクライアントが女性向けにアプローチして女性集客を増やしたいのであれば、
Webデザイナーは情報の整理をし、女性が好む色合いで魅力的なデザインをしてあげることです。

## まとめ ( Webデザインが上達するコツ )
Webデザインはセンスよりも多くの知見の方が大切です。
より多くのデザインに触れ、より多くのデザインを作ることによりWebデザイン力が成熟します。
様々なデザインを探すのは大変かと思いますので、下記のようなまとめてあるサイトを活用ください(^^)
[MUUUUU.ORG](https://muuuuu.org/)
[Dribbble](https://dribbble.com/)

また、デザイン初心者の方はまず [Cocoda!](https://cocoda-design.com/) を使って勉強すると楽しく学べるかもしれません。

この記事が良いと思った方は、LGTMをしていただければ嬉しいです！
フォローも是非お願い致します(^^)
LaravelでFirebase Admin SDK for PHPを利用する

## インストール

```
composer require kreait/firebase-php
composer require kreait/laravel-firebase
```

## Laravelに設定追加

```php:config/app.php
        /*
         * Package Service Providers...
         */
        Kreait\Laravel\Firebase\ServiceProvider::class,
```


```ini:.env
APP_NAME=Laravel
APP_ENV=local
# ... 省略 ...
FIREBASE_CREDENTIALS=../firebase_credentials.json
```

## config配下に設定ファイルを作る

```
php artisan vendor:publish --provider="Kreait\Laravel\Firebase\ServiceProvider" --tag=config
```

`config/firebase.php`が作成される。

## 試してみる

```php:app/Http/Controllers/FireTestController.php
<?php

namespace App\Http\Controllers;
use Kreait\Firebase\Auth;

class FireTestController extends Controller
{
    private $auth;

    public function __construct(Auth $auth)
    {
        $this->auth = $auth;
    }

    public function show()
    {
        $anonymous = $this->auth->signInAnonymously();
        print_r([$anonymous->idToken(), $anonymous->firebaseUserId()]);

        return view('welcome');
    }
}
```

これで、idTokenとfirebaseUserIdが取得できました。
あとはトークン使って好きなように。

idTokenは有効期限が1時間のアレ。
firebaseUserIdは、FirebaseConsoleのAuthenticationページでユーザーUIDと表示されているヤツ。

## idTokenの再取得をする処理は以下にまとめた
[LaravelでFirebase Admin SDK for PHPを利用する(トークン再取得編)
](https://qiita.com/r_ishimori/items/8a780fe0d3682447e2eb)
Microsoft SQL Server Management Studio(SSMS)で同じサーバ、違うデータベースをINNER JOINする方法

#はじめに
Microsoft SQL Server Management Studio(以下SSMS)を使っている人、あまり見かけないような。。。本記事は、自分用のメモ拡張版ですので、見やすさはご愛嬌でお願いします。

#問題点
私はこれがやりたくて苦労しました。
ネットの文献を見ていると、

INNER JOIN DB-B.table-B ON DB-A.table-A = DB-B.table-B

と書いているけど、どうも成功しない。

![プレゼンテーション1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533911/af439dfe-26ce-ec0d-77d8-4054250bcc3d.jpeg)


#答えは　.（ドット）の数にあり。
SSMSの場合
**INNER JOIN DB-B..table-B ON DB-A..table-A = DB-B..table-B**

**データベース名とテーブル名の間の.(ドット)は2個！！**

現場からは以上です。
秀丸で強調定義ファイルの直接編集を少し楽にするマクロ 

秀丸 Ver.8.89以降のファイルタイプ別 強調定義の設定で「.hilightファイル」から直接読み込むモードがサポートされたようなので 昔作ったマクロを蔵出ししてみる。

## 秀丸とは
言わずと知れたwindows用の国産テキストエディタ　

 - [秀まるおのホームページ(サイトー企画)](https://hide.maruo.co.jp/software/hidemaru.html)

数か月ごとくらいにVSCode起動しては秀丸に戻ってくるを繰り返してる
さすがに20年以上使ってるともうよそに移行できない

## DecoHilight.mac
秀丸エディタの強調表示ファイルを装飾するマクロ

- [マクロライブラリ - 秀まるおのホームページ](https://hide.maruo.co.jp/lib/macro/decohilight-100.html)
- [DecoHilight](https://github.com/eamat-dot/DecoHilight) (Githubリポジトリ)

**デモ**
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249833/991b5be4-0822-d4e6-8205-b6fdbc1cc493.gif)

### 秀丸のシンタックスハイライト設定は結構面倒くさい  

設定ダイアログからポチポチやるのは複数のタイプ別設定を作ってしまった後だとしんどい。なら強調定義ファイル(hilight)はテキストファイルだし直編集すればいいかって安易に考えるんだけど、これがまたわかりにくい。
もともとインポート/エクスポート用で人力で編集する前提ではなかったのかな？ 強調部のフラグは10進数表記でどのビットが立ってるのかさっぱりわかんない。
デザイン(色)も **強調1** 、**特に強調1** みたいな感じでスコープに意味づけがなものが基本なので（htmlタグや文字定数、コメントなど意味のあるものもある
）カラーテーマだけ他人と共有して後から当てるってのもやりにくいのよね。


**DecoHilight.mac** はそんな強調定義ファイル に過分に冗長気味なコメントを挿入し、定義のとおりに色付けします。

* VSCodeの素敵なエクステンションのように自動でカラーピッカーが出てきて色変更が捗るような機能はありません。
* **ColorSet** の項目の色はカラーマーカーで一時的に塗っているだけなので、編集したら消えます。

## その他、知らない間に便利になってた秀丸の機能とか

 - ファイルタイプ別にタブの色を変えられる
 - `if ()` `while` 等のネスト時に縦線でインデントラインが表示できる
 - カーソル位置と同じ単語を自動ハイライト

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249833/69b8b983-f665-0268-aa4b-9093c0e125cd.gif)

インデントラインと単語自動ハイライトはVSCodeでうらやましかった機能。実装されてるの知らんかった。便利

## ついでにファイル保存時にタブ変換する機能があることを知った。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249833/fb584baf-c855-46bd-7bb7-7994f678ce73.png)

どうせ保存時に舐めて変換やるなら [EditorConfig](https://editorconfig.org/) 標準対応してくれてもいいのよ…
なおマクロで実現可能にしたものを配布されている方はおられます。

- [EditorConfigを反映させるマクロ - h-tom's Warehouse](http://htom.in.coocan.jp/macro/EditorConfigSet.html)
シェルスクリプトでフォルダ内のファイルを順に処理

[1.やりたいこと](#やりたいこと)
[2.コード紹介](#コード紹介)
[3.実行例](#実行例)
[4.おまけ](#おまけ)

#やりたいこと
フォルダ内のデータ（名前）を取得します。
本記事ではフォルダ内ファイルの拡張子を.txtから.logに変更するループ文のシェルスクリプトを紹介します。

#コード紹介
**現在のフォルダの状況**

```text:実行前の状況
$ ls
1.txt   2.txt	3.txt	4.txt	5.txt	main.sh
```

```shell:main.sh
#!/bin/sh
for filename in *.txt
do
	mv ${filename} ${filename%.txt}.log
done
```

#実行例
```text:main.shの実行
sh main.sh
```

```text:実行後の状況
$ ls
1.log   2.log	3.log	4.log	5.log	main.sh
```

.txt拡張子が.logに変更されていることがわかります。

#おまけ
何十万のデータに番号をつけたい場合も利用できますね。
for分の途中でカウンタを文字列付与すれば一気に大量のデータに番号をつけることもできます。

```shell:main.sh
#!/bin/sh
cnt=1
for filename in *.txt; 
do
	mv ${filename} data_${cnt}.log;
    #cnt変数のインクリメント 
	cnt=`expr ${cnt} + 1`
done
```

```text:実行後の状況
$ ls
data_1.log  data_2.log  data_3.log  data_4.log  data_5.log  main.sh
```
airportコマンドなしでWifi通信状態を確認できる

同僚さんがこんな記事を書いてくれていましたが、コマンド不要でWifiの通信状態が確認できることを知ったので共有。
ちなみにmacOSです。

[MacOSのあまり知られていない無線LANユーティリティコマンドairportの紹介](https://qiita.com/zackey2/items/c149c5b5eb6a1ba36ba0)

ステータスバーのwifiアイコンをoptionキーを押しながらクリックすると以下のように表示されます。
<img width="345" alt="スクリーンショット 2020-06-02 11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89213/5d866ea2-1090-719f-84a2-57480e627da3.png">

以上です。便利ですね
Railsアプリを作成してGitHubにSSHでPush

VPSのセットアップしてcapistranoでデプロイする流れで、Railsアプリを作成する必要があったので簡単にまとめます。情報量の関係上、Rails5です。安全に行きたいので。

## 環境
Rails 5.2.2
Ruby 2.4.1
MySQL 5.7

## You're on Railsを表示
```zsh
$ mkdir sample_app
$ cd sample_app
$ touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
```
```Dockerfile:Dockerfile
FROM ruby:2.4.1

RUN apt-get update -qq && \
  apt-get install -y build-essential \ 
  libpq-dev \        
  nodejs           

RUN mkdir /app_name 
ENV APP_ROOT /app_name 
WORKDIR $APP_ROOT

COPY ./Gemfile $APP_ROOT/Gemfile
COPY ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
COPY . $APP_ROOT
```
```docker-compose.yml
version: "3"
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    links:
      - db

```
```rb:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.2'
```
```Gemfile.lock
#空
```
```zsh
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
$ docker-compose build --no-cache #--no-cacheオプションが無いと、bundle installが実行されないことがある
```
```config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db

development:
  <<: *default
  database: app_name_development

test:
  <<: *default
  database: app_name_test

production:
  <<: *default
  database: app_name_production
  username: app_name
  password: <%= ENV['APP_NAME_DATABASE_PASSWORD'] %>
```
```zsh
$ docker-compose up
```
```zsh
$ docker-compose run web rails db:create
```
http://localhost:3000 にアクセスして`Yay!You're on Rails!`を確認

## 適当なページを作成
```zsh
$ docker-compose run web rails g controller tests index
```
```config/routes.rb
Rails.application.routes.draw do
  get 'tests/index'
  root to: 'tests#index'
end
```
http://localhost:3000 にアクセスして表示を確認

## sshキーペアを作成しGitHubに登録
すでに登録済みの場合はとばしてください。

```zsh
$ mkdir -p ~/.ssh/github
$ cd ~/.ssh/github
$ ssh-keygen -f id_rsa
$ vim ~/.ssh/config
```
```yml:~/.ssh/config
Host github.com #ここが「github」だと動かないので注意
  HostName github.com
  Port 22
  IdentityFile ~/.ssh/github/id_rsa
  User git
```
```zsh
$ pbcopy < id_rsa.pub #公開鍵をクリップボードにコピー
```
その後以下の手順でGitHubに登録

- GitHubにログイン
- 右上のアイコン > Settings > SSH and GPG keys に移動
- New SSH keyをクリック
- クリップボードにコピーした公開鍵をペーストして保存

## GitHubにリポジトリを作成
- GitHubにログイン
- 画面右上のアイコン > Your repositoriesをクリック
- Newをクリック
- リポジトリ名を入力し Create repository をクリック

## Push
```zsh
$ git add -A
$ git commit -m "First commit"
$ git remote add origin git@github.com:<githubのアカウント名>/<リポジトリ名>.git
$ git push -u origin master
```
VSCodeでプロジェクト用のPython仮想環境をvenvで準備する

# はじめに

前記事で環境構築と静的解析まで実施しましたが、
複数のプロジェクトを同環境で開発する場合、使うモジュールや違うバージョンのモジュールを使用したりするので、
プロジェクト毎のPython仮想環境を準備します。

前記事
[VisualStudioCodeでPython開発環境構築 (0からflake8による静的解析及びコード整形まで)](https://qiita.com/enya314/items/374cca3c1b29dac1baab)

# 動作確認環境

Windows 10 64bit
Python 3.8.3
VSCode 1.45.1

# Python仮想環境構築

## プロジェクト用のディレクトリ作成

VSCodeの上部メニューのTerminalからNewTerminalを開く。
（PowershellかCmdでもOK）
任意のディレクトリにプロジェクトディレクトリを作成します。

```
PS C:\work> mkdir TestProject
PS C:\work> cd TestProject
```

## 仮想環境の作成

以下のコマンドを実行し仮想環境を構築します。

```
PS C:\work\TestProject> python -m venv project_env
```

仮想環境構築後は以下のようなファイル群が作成されています。

```
PS C:\work\TestProject> cd project_env
PS C:\work\TestProject\project_env> ls


    ディレクトリ: C:\work\TestProject\project_env


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/06/02     15:00                Include
d-----       2020/06/02     15:00                Lib
d-----       2020/06/02     15:00                Scripts
-a----       2020/06/02     15:00            126 pyvenv.cfg
```

## PowerShellのポリシー変更

仮想環境をActivateするためには、
その機能を持つPowerShell Scriptを実行する必要があるそうですが、Windows10では標準で実行できないようです。

そのため、PowerShellのポリシーを変更します。

### 1．管理者権限でPowerShellを開く

　検索からPowerShellを見つけて管理者権限で開きます。
![Powershell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/456968d1-8e8f-ccbf-ef68-845fd41b4b79.png)

### 2．下記コマンドをPowerShellで実行

```
Set-ExecutionPolicy RemoteSigned
```

## Python仮想環境をVSCodeに反映

### 1. プロジェクトディレクトリをVSCodeで開く
  VSCode上部メニューからFile⇒Open Folderをクリックし、作成したプロジェクトディレクトリを開く。

### 2. 確認用pythonファイル作成
　プロジェクトフォルダ内にPythonファイルがないと仮想環境が読み込まれないため、任意の*.pyファイルを作成する。

### 3. 仮想環境の反映確認
　仮想環境が正常に読み込めた場合、下記のように左下のPythonのバージョン情報の横に読み込んでいる仮想環境名が表示されます。
![venv2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/50bbc3f8-f447-bdb4-ad83-6667e43c0c54.png)

### 4. ターミナルの確認
　仮想環境が反映された状態でターミナルを開くと、下記のように仮想環境がActivateされた状態で開きます。
　真っ新な環境となるため、pip freezeでインストールパッケージ一覧を表示しても空の状態になります。

![terminal2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/31ff7d14-7e03-31e9-f5a6-30c917f0c8f4.png)


## 必要なモジュールのインストール

仮想環境では前記事で設定していた静的解析ツールもインストールされていない状態となりますので、仮想環境にもインストールします。
※仮想環境反映時にVSCode側からinstallの指示が出ますのでそちらでインストールしても大丈夫です。

```
pip install flake8 autopep8
```

インストール後のパッケージ一覧
![pipfreeze.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/23019b03-e4c9-aaa4-99fc-50a9ecb66be3.png)

仮想環境構築は以上です。お疲れさまでした！

## 追記：再度VSCodeを起動した際に仮想環境が反映されていない

複数のバージョンのPythonモジュールがインストールされていたりすると、
プロジェクトを再度開いた際に仮想環境が反映されないことがあります。

その場合は下図の通り、
左下のPython情報をクリックし、表示されるリストから仮想環境を選択してください。

![select_env.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/9ddd9516-e08b-241a-072a-1f3ec0e39471.png)



## 参考にした記事

[Windows10のVSCodeでvenvを利用するときの注意点](https://qiita.com/Avocado/items/3e71870815d6c54c1eea)
UE4で新しいWin APIを使う

UE4で比較的新しめのWindowsAPIを使おうとするとできなかったのでその関数を使うdllを作って対応した。
ここではその内容を記録する。

# 発生した現象

UE4.24で[GetDpiForWindow](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow)を利用しようとすると以下のようなエラーが発生してコンパイルできない。


```text
CompilerResultsLog:    E:\Users\hotta\Documents\Unreal Projects\GoogleSpeechKitTest\Source\GoogleSpeechKitTest\MyTest.cpp(9) : error C2039: 'GetDpiForWindow': is not a member of '`global namespace''
CompilerResultsLog:    E:\Users\hotta\Documents\Unreal Projects\GoogleSpeechKitTest\Source\GoogleSpeechKitTest\MyTest.cpp(9) : error C3861: 'GetDpiForWindow': identifier not found
```

# 原因

GetDpiForWindowが定義されているWinUser.hを確認すると

```
#if(WINVER >= 0x0605)
```

のなかで関数が定義されている。
UE_4.24/Engine/Source/Programs/UnrealBuildTool/Platform/Windows/UEBuildWindows.cs
を確認すると以下のようになっておりWINVERは-x0601か0x0602あたりにしかならなさそうで0x0605に達しない。
([UE4のWindowsにおけるマルチタッチについて : まったり開発日誌](http://blog.livedoor.jp/tarotaro_naka/archives/55434643.html)参照)
このため、関数が見つからないようになっていたと思われる。

```csharp
/// <summary>
/// Value for the WINVER macro, defining the minimum supported Windows version
/// </summary>
public int TargetWindowsVersion = 0x601;

...

if (Target.WindowsPlatform.bUseWindowsSDK10)
{
       CompileEnvironment.Definitions.Add(String.Format("_WIN32_WINNT=0x{0:X4}", 0x0602));
       CompileEnvironment.Definitions.Add(String.Format("WINVER=0x{0:X4}", 0x0602));
}
else
{
       CompileEnvironment.Definitions.Add(String.Format("_WIN32_WINNT=0x{0:X4}", Target.WindowsPlatform.TargetWindowsVersion));
       CompileEnvironment.Definitions.Add(String.Format("WINVER=0x{0:X4}", Target.WindowsPlatform.TargetWindowsVersion));
}
```

# 対応方法

とりあず中でGetDpiForWindowを使う以下のような関数を提供するdllを使うようにすると利用できた。
New PluginのThird Party Libraryのテンプレートを参考にしてdllとそれを利用するプラグインを作って対応した。
（もっと簡単な対応法があったら知りたい）

```cpp
unsigned int GetDPIFromWindow(void *hwnd)
{
#if defined _WIN32 || defined _WIN64
	return ::GetDpiForWindow((HWND)hwnd);
#else
	return 0;
#endif
}
```

2023/10/12追記
以下の記事のようにbuild.csのPublicDefinitionsでWINVER関係の定数を再定義する方法もあるみたいです。
[UnrealEngineにおいてWindowsのタッチをシミュレートしてみる - Qiita](https://qiita.com/mechamogera/items/41d6eed7a811e0c0c486)
【MicrosoftAzure】Azure for Studentsを使ってみる。

#Azure for Students(AFS)とは

　MicrosoftAzureの学生用サブスクリプション。明確なメリットは以下の2つ。

* １２ヶ月間、$100内で無料で使える
* クレカの登録が必要ない。

詳しいことは[FAQ](https://azure.microsoft.com/ja-jp/free/free-account-students-faq/)で

##用意するもの
* 学校のメールアドレス
* AzureにログインするためのMicrosoftアカウント。新しくアカウントを作成する場合は[こちら](https://signup.live.com/newuser.aspx?mkt=ja-jp)から、新しいメールアドレスを取得をクリックしてください。(***@outlook.jpは使用できません。と出る場合が既に使われている可能性があります。他の候補で試してみてください。)

Microsoft用のメールアドレスに、サブスク用の大学機関メールアドレスを紐づける形で登録します。
##有効化の方法


1. [Azure for Students](https://azure.microsoft.com/ja-jp/free/students/)にアクセス
2. 用意したMicrosoftアカウントにサインイン
3. **今すぐアクティブ化**をクリック
![top.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/6e636994-2e54-7e0e-6102-c56e0c8693a9.jpeg)
4. まず本人確認が行われます。電話番号を入力して携帯電話に届いたSMSの確認コードを入力してください![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/683b14da-0295-0c07-3d00-54566a15d33a.png)
<img width="375" alt="20200602_063752000_iOS.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/e806d8bd-4017-d1f3-9f07-3aec50b0fcbd.jpeg">  
5. 確認方法に「学校のメールアドレス」を指定して、学校のメールアドレスを記入し「教育機関ステータスの確認」をクリックしてください。
![2019-05-14 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/aa9ca467-c27a-2217-0baa-1fb4f9d661c1.png)  
6.以下のような表示が出たら、学校用のメールを確認してください。1度行ってもメールが届かない場合があります。何度かチャレンジしてみてください。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/7e391c83-72be-8fba-1ae0-d43b0c6236f0.png)  
7.画像のようなメールが届きます。URLをコピペしてアクセスしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/15ec0bdf-806e-3bd5-acd3-fbe344b4e399.png)  
8.自分の情報を入力して「次へ」をクリックしてください。重要な通知用の電子メール アドレスの項目は、サブスクリプションの期限やAzureの更新情報に関する内容のメールが来ます。個人のメールアドレスでも、
学校のメールアドレスでも、新しく作成したメールアドレスでも構いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/82dd1462-120b-21e7-bc33-0644859307b2.png)  
9.しばらくしたら、アグリーメントの項目に移ります。上のチェックボタンは必須ですので、チェックして「サインアップ」を押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/2b685a95-fa1a-04e9-ae57-e55527b6956c.png)  
10.Azureポータル画面にアクセス出来たら完了です。サインインしているアカウントが複数ある場合、以下のような画面が表示されます。**必ず新しくつくったアカウントでサインインしてください。大学用のアカウント自体にはAzure for Studentsサブスクリプションは有効化されていません。**![signin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/704f6aa1-cc1b-5d41-f80b-e359bd200887.jpeg)  
11.Azureポータルへは、Azureのトップページからポータルをクリックすることでアクセスできます。この時、新しく作ったアカウントでサインインしているか必ず確認してください。![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/793fd7de-2588-1c99-c794-c8c261a74f92.png)

## 有効になっているかの確認方法
[ポータル](https://portal.azure.com/#home)にログインしてサブスクリプションと入力し、鍵のマークのサービスをクリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/16a4c0c5-75b8-38a0-ec3a-8e606a07156b.png)
Azure for Studentsの状態がアクティブになっていれば有効化されています。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416672/63102f8a-383b-a35e-ce6d-a5064344852a.png)
macとwinでpyInstallerを使う時経験した不具合と対処法

pyInstalllerの設定をwindowsとmacで経験した事を書き留めたいと思います。
<b>macOSは10.13.5 Hight Sierra、windows 10 1909です。</b>

###Mac:

1. pyenvの問題。PyInstallerを使うと、OSErrorが発生した。対処はpyenvの<b>再インストール。</b>

```PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install バージョン
```

注意：envのアンインストールは不要だった。pip listで確認できるすでにインストールしたモジュールは失われていなかった。
２．pyInstallerの再インストール必要。
上記「モジュールは失われていなかった」と書いた。pip listで確認すると存在していることが確認できた。しかしpyInstallerを実行してもまだOSErrorが発生した。pip uninstall pyInstallerとpip install pyInstallerを実行し、再インストールした。

Mac環境でpython - pyenvを使う上で、インストール時--enable-sharedのオプションを使うことは重要なようです。"PYTHON_CONFIGURE_OPTS="--enable-shared" は「パイソン設定オプションでシェアを有効にする」という指定なのでしょう。

下にWindowsの問題点で書きますが、WindowsではpyInstallerインストール時、「実行ファイルがAppData下にインストールされたので、環境変数でパスを指定しなさい」と言われます。
「シェアする」(mac)という行為と「パスを通す」(win)という行為は違うようですが、macとwinを使う人々にとっては「使いやすくする」という設定、言い換えるとカスタマイズだと思います。

+ <b>「よく読めば自分の好みにできるが、それに気づかず『使えないなぁ、もうやめる！』」と、</b>
+ <b>「１次情報と周辺情報などかき集めて自分の知見を積み上げ使い続ける」と、</b>
+ <b>「ソフトウェアは最適なUX環境が提供されるものだ」など</b><br>
が混在する事を気付かされます。

###Win： 
1. pyInstallerインストール完了した時、そのメッセージには、"C:\Users\USER_NAME\AppData\Roaming\Python\Python(バージョン)\Scripts"にインストールしたから、環境変数でパス指定したほうがいいという文章がある。
2.システム環境変数のPathに"C:\Users\USER_NAME\AppData\Roaming\Python\Python(バージョン)\Scripts"を加える。
3.自分の場合そのパスを一番上の順位にする。windowsは指定した実行ファイルを上から順番に探していくので、順位を上にすることは不要だと思うが、最上位にしても問題はないと判断した。
3. pyInstallerオプションで、--onedir or -p（1ディレクトリ）、--onefile or -F（1ファイル）、--noconsole or -w（コンソールを表示なし）、--clean（ビルド前に前回のキャッシュと出力ディレクトリを削除）、--icon（タイトルにアイコン表示）
4. --iconオプション設定時、pythonプログラムコード内で、iconのicoファイルのある場所を指定するのだが、その書き方はフルパスで記述すること。自分の場合、pyInstallerで生成は成功したのだが、distフォルダにあるexeファイルはfata errorが発生した。フルパスで記述し直したところfatal error問題は解決した。
ExcelVBA_最終行、最終列の取得




#最終行の取得
　ExcelVBAで多用する最終行の取得と最終列の取得についてまとめる。

##**1.　.End(xlDown)：Ctrl+↓ を使う方法**
　途中に空欄がある場合は空欄の一つ上のセルが最終行として認識される。
　入力されているセルが1行目のみの場合はその列の最終行は「1048576行目」と認識される。 

```VB:最終行の取得
最終行 = Cells(1, 1).End(xlDown).Row
```

##**2.　.End(xlUp)：Ctrl+↑を使う方法**
　入力されているセルが1行目のみの場合はその列の最終行は「1行目」と認識される。
　1行目のセルに何も入力されていなくても最終行は「1行目」と認識されてしまう。

```VB:最終行の取得
最終行 = Cells(Rows.Count, 1).End(xlUp).Row
```

##**3.　CurrentRegionを使う**
　途中に空白行（何も入っていない行）がある場合は、そこまでの行になってしまう。

```VB:最終行の取得
With Range("B2").CurrentRegion
　　最終行 = .Item(.Count).Row
End With
```

##**4.　SpecialCells(xlCellTypeLastCell)を使う**
　罫線が引いてあればそこまで範囲に入ってしまう。
　行高をデフォルトから変えているだけでも、その行まで範囲に入ってしまう。

```VB:最終行の取得
最終行 = Cells.SpecialCells(xlCellTypeLastCell).Row
```

##**5.　UsedRangeを使う**
　罫線が引いてあればそこまで範囲に入ってしまう。
　行高をデフォルトから変えているだけでも、その行まで範囲に入ってしまう。

```VB:最終行の取得
With ActiveSheet.UsedRange
　　最終行 = .Item(.Count).Row
End With
```

##**6.　Findメソッドを使う**
　Findメソッドを使うため、[検索と置換]ダイアログボックスに表示される設定が変わってしまう。

```VB:最終行の取得
最終行 = Cells.Find(What:="*",LookIn:=xlFormulas, SearchOrder:=xlByRows,SearchDirection:=xlPrevious).Row
```


##**■ユーザー定義関数**
　毎回どの方法で最終行を取得するか面倒だったため、Findメソッドを使ったユーザー定義関数を作成。
　[検索と置換]ダイアログボックスの検索値に「*」と入力されてしまうが、大勢に影響ないと判断した。
　同様のやり方で最終列を取得する関数も作成。

```VB:最終行の取得
Function rowLast(sheetName As String, column As Integer) As Long
'===========================
'関数名  :   rowLast
'目的    :   最終行を求める
'引数    :   検索する列番号
'返値    :   最終行番号
'===========================
On Error GoTo errExit
   rowLast = Sheets(sheetName).Columns(column).Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
Exit Function
errExit: rowLast = 0
End Function
```
```VB:最終列の取得
Function colLast(sheetName As String, row As Integer) As Long
'===========================
'関数名  :   colLast
'目的    :   最終列を求める
'引数    :   検索する行番号
'返値    :   最終列番号
'===========================
On Error GoTo errExit
   colLast = Sheets(sheetName).Rows(row).Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).column
Exit Function
errExit: colLast = 0
End Function
```
ESXi7: ホストのIPアドレスを固定する

###ホストPCのIPアドレスを変更、固定します。

Webサービスから、
ホスト -> アクション -> サービス -> SSHの有効化

[参考](https://hypervisualization.net/2019/01/vmware-vsphere-hypervisor65esxiipssh.html)

```shell:現在のIP情報取得
$ esxcli network ip interface ipv4 get
#Name  IPv4 Address  IPv4 Netmask   IPv4 Broadcast  Address Type  Gateway  DHCP DNS
#----  ------------  -------------  --------------  ------------  -------  --------
#vmk0  192.168.0.XX  255.255.255.0  192.168.0.255   STATIC        0.0.0.0     false

```

```shell:IPアドレス設定
$ esxcli network ip interface ipv4 set -i vmk0 -I 192.168.0.XX -N 255.255.255.0 -t static
#ターミナルを再起動して設定したIPアドレスでログイン確認
```

Webサービスに新しいIPアドレスでログインし、
ホスト -> アクション -> サービス -> SSHの無効化

終了。
Cloudantでtimestampで検索をかける

# はじめに
Cloudantでtimestampで検索をかけるにはSeach Indexを作成する必要があるようですが、方法が分かりやすく紹介されているページを見つけられなかったので備忘録のために書きました。


## Documentの用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/50631a55-f73b-6ed2-d779-eb5400251cc0.png)

サンプルのドキュメントを追加します
`name`, `timestamp`の2つのフィールドを持つこととします。

```
{ "name": "satoshi", "timestamp": "2020-05-27T14:04:22+09:00" }
```


## Search Indexの作成方法

１．データベース作成後、Design Documents > New Search Indexを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/84ca9bc8-b102-854a-8caa-4a0eb17532db.png)

２．Search index の情報を設定する

_desing/ `xxxx`、`Index name`、Seach index function、Analyzerを設定して、Save Document and Build Indexをクリック



```javascript:searchIndexFunction

function (doc) {
  index("name", doc.name, { "store": true });
  index("timestamp", doc.timestamp, { "store": true });
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/db4ce53f-01c5-f4df-5add-46957711af82.png)


注意点

- `xxxx`、`Index name`は後で使用することになるのでちゃんとした名前を設定する
- 検索結果として返してきてほしいフィールド名を `index("xxxx", doc.xxxx, { "store": true });` で指定する
- Analyzer > Single > Typeを `Keyword` に設定する

３．以下のクエリを試す

```
timestamp: [ "2020-05-27T14:04:22+09:00" TO "2020-05-30T14:04:22+09:00"]
```

指定範囲のDocumentが取得できれば成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/e18b0461-065b-5908-2cb1-43a2743f54ac.png)

設定は以上


## 【おまけ】 Node.jsでtimestampで検索

```
npm install @cloudant/cloudant
```

```javascript:test.js

  const Cloudant = require('@cloudant/cloudant');
  const cloudant = Cloudant({ 
          url: "",
          plugins: { iamauth: { iamApiKey: "" } } 
      });
  
  const db = cloudant.db.use("dbName");

  const start = '2020-05-27T14:04:22+09:00'
  const end = '2020-05-30T14:04:22+09:00'
  const payload = {
      q: `timestamp: ["${start}" TO "${end}"]`, 
      limit: 200 // 検索結果で返ってくるのはデフォルトで10件 最大でも200件
  }

  // Search Indexの作成方法で指定したxxxx, Index nameを1つ目、2つ目の引数で指定
  db.search('Index', 'timestampIndex', payload)
  .then((result) => {
      console.log(JSON.stringify(result, null, 2))
  })
  .catch((err) => {
      console.log(err)
  });
```


UIで取得したのと同じ結果が取得できました。


```
> node test.js
{
  "total_rows": 2,
  "bookmark": <省略>,
  "rows": [
    {
      "id": "c61fa495d24d4b9c7fddd59109e75386",
      "order": [
        1,
        0
      ],
      "fields": {
        "name": "yoshino",
        "timestamp": "2020-05-27T14:04:22+09:00"
      }
    },
    {
      "id": "07d7c46dbce4b2820d0094a085ff4f11",
      "order": [
        1,
        0
      ],
      "fields": {
        "name": "satoshi",
        "timestamp": "2020-05-27T14:04:22+09:00"
      }
    }
  ]
}
```
VSCode の Prettier でファイル毎にフォーマットを変える

プロジェクトのルートに .prettierrc を作成して、下記のように記述
下記の場合は、プロジェクト内の SCSS ファイルはシングルクォートを使って、 JS ファイルはダブルクォートを使いたい場合。

```
{
  "overrides": [
    {
      "files": "*.scss",
      "options": {
        "singleQuote": true
      }
    },
    {
      "files": "*.js",
      "options": {
        "singleQuote": false
      }
    }
  ]
}
```
.prettierrc
UiPathでExcelVBAのエラーをハンドリングする

##UiPathでVBAエラーをハンドリングすることの重要性
仕事柄、UiPathからExcelVBAを呼び出して業務を自動化することがよくあるが、ここでよく困ることがある。
UiPath側でVBAのエラーハンドリングを組み込んでおかないとUiPathが異常を検知できずにずっと停止してしまうのである。
手動でUiPathを起動するなら最悪エラーウインドウを見て気付けるが、自動実行で夜間に動くものだと朝になってやっと気づくなんてことも…
ということでUiPathからVBAエラーを最低限検知できる仕組みを紹介する

##VBA側の準備
以下が例、重要なのはVBAの中でもちゃんとエラーハンドリング処理を入れてUiPathに返す値を定義すること。

```vb
Function vbaError(stErrorFlg As String)
    On Error GoTo dummyError
    If stErrorFlg = "True" Then
        i = 1 / 0   '0除算で強制的にエラーを起こす
    End If
    
    vbaError = ""  'エラーがない場合は""を返す
    Exit Function
dummyError:
    vbaError = Err.Number & "," & Err.Description  'エラーが発生したときにUiPathに返すエラー内容
End Function

```
（Errをそのまま返したいところだがErrObjectクラスはインスタンス化できないらしい…
[こちら](https://akashi-keirin.hatenablog.com/entry/2019/05/01/165546)のサイトを参考にしながらクラス定義してあげればできなくは無いんだろうけど…）

##UiPath側の準備
あとは、UiPath側ではこのようにExecuteMacroアクティビティのOutputを適当な変数で受け取ればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/c9d549dd-3193-5b89-4ef0-d2621f6f1166.png)

受け取った変数が空っぽかどうかでエラーの有無を判定。エラーの場合はThrowアクティビティを使ってexceptionを発生させる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/90195992-fdd9-84ab-f55d-bdb9766a2427.png)
##結果
このように、VBAのエラーコード、エラーメッセージを表示することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/4f760864-228b-7ed7-f02f-48da2cf4e774.png)

VBAの保守で悩まないためにもエラーハンドリングはちゃんと入れておこう。
Lambda@Edgeで追加したいhttpヘッダをapacheの設定から持ってくる

# httpd.conf → Lambda@Edge

私のサイト [devel.keys.jp](https://devel.keys.jp) は、昼間は EC2 上の Apache httpd で動かしているんですが、夜中は S3 + CloudFront でホストするようにしています1[^free-tier]。

[^free-tier]: 無料枠が月750時間までだと24時間動かしていると他のインスタンスを立てにくいので、1〜7時までインスタンスを落として無料枠をセーブしているのです

というときに、S3 でも httpd と同じヘッダを加えたいなーと思って作りました。

EC2 の httpd の設定は次のようなものです:

```apache:httpd.conf
    Header set X-XSS-Protection "1; mode=block"
    Header set X-Content-Type-Options nosniff
    Header append X-Frame-Options SAMEORIGIN
    Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
```

これを実現するには CloudFront の [Lambda@Edge](https://aws.amazon.com/jp/lambda/edge/) を使って、`Viewer Response` と `Origin Response` の両方をトリガー[^dual-trigger]にして動かす、次のような Python の Lambda を書きます。(JavaScriptで書く場合は、[Amazon提供のチュートリアル](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-how-it-works-tutorial.html
)を見てください)

[^dual-trigger]: CloudFront のキャッシュにヒットしたときは Viewer Response が、キャッシュミスした場合は Origin Response が、それぞれトリガーとして動くようになっている(らしい)です。参考: [CloudFront Events That Can Trigger a Lambda Function](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html)

```python:lambda_function.py

def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']

    if int(response['status']) == 200:
        response['headers']['strict-transport-security'] = [{'key': 'Strict-Transport-Security', 'value': 'max-age= 63072000; includeSubdomains; preload'}]
        response['headers']['x-content-type-options'] = [{'key': 'X-Content-Type-Options', 'value': 'nosniff'}]
        response['headers']['x-frame-options'] = [{'key': 'X-Frame-Options', 'value': 'SAMEORIGIN'}]
        response['headers']['x-xss-protection'] = [{'key': 'X-XSS-Protection', 'value': '1; mode=block'}]

    return response
```

一度設定したヘッダを変えることはほとんどないと思うんですが、せっかくなので[^perl]これを自動化する Perl スクリプトを書きました。

[^perl]: 最近 Perl のコードを書いてないので書きたくなって、理由を付けて書いてみました

```perl:lambda_header_convert.pl
#!/usr/bin/perl
while (<>) {
    s/^\s*(.*?)\s*$/$1/;
    if ( /^Header\s+(set|append)\s+([\w-]+)\s+"?([^"]+)"?$/ ) {
        my $h_key = lc($2);
        print "response['headers']['$h_key'] = "[{'key': '$2', 'value': '$3'}]\n";
    }
}
```

よくテストしていないので、実際に使ってみたいという人はテストをお忘れなく！
【GCP】Cloud Functions の Go 1.13 でファイル構造に変更があった


## Cloud Functions Go 1.13 GA :tada:

GCF/Go 1.13 が GA になったので Go 1.11 から移行してみた。しかし、デプロイに失敗するようになった。

https://cloud.google.com/functions/docs/release-notes#May_28_2020

## 原因

コード内で設定ファイルを読み込むようにしていたが、GCF/Go 1.13 からファイルの構造が変更され読み込みエラーが起きてしまった。

## 調査

どのようにファイルの構造が変更があったのか調べたところ、ファイルの構造を調査したリポジトリを発見。

https://github.com/bcollard/find-go-cloud-function

どうやら、静的ファイル保存ディレクトリは以下に保存されるようだ。
`/workspace/serverless_function_source_code/`

ファイル構造について、公式ドキュメントでは見つけることはできなかった。

## 対応

コードの静的ファイルを指定している箇所を下記のように変更した。

```diff
- ./xxx.json
+ /workspace/serverless_function_source_code/xxx.json
```

無事、デプロイに成功した。
CircleCIとは何か調べてみた。

# CircleCIとは
Sass型のCI/CDサービスのことです。クラウド上のコンテナorVMを実行環境いとして使用します。
CircleCIではコンテナの利用を推奨しているようです。

## 何ができるの？？
1.ビルド
ソースコードから実行可能なアプリケーションを構築します。
具体的には、Dockerイメージのpull、依存パッケージのインストール、コンパイルなどです。

2.テスト
UTなどのテストコードを実行して動作確認をしたり、Rubocop(Ruby)などのコードスタイルチェックなどを行います。

3.デプロイ
ビルドしてテストが通ったものを本番環境や検証環境などにリリースします。


##メリット
1.環境構築コストが低い
・Saasだから
・Web-UIで初期設定を少しやるだけ
・冗長化とかも勝手にされている
・Jenkinsの場合、自前でJenkins用のサーバを立てる必要がある

2.運用コストが低い
・Saasだから
・サーバーメンテナンスや故障時の対応をやる必要がない

3.ymlファイルで設定できる
・Jenkinsの場合、Web-UIで細かい設定までできるが、個人的なものになりがち


##デメリット
1.バージョン管理でSVNを使っているプロジェクトでは使えない
・GitHub/Bitbucket連携が前提

2.リアルタイムにビルド実行ができない
・定期実行はできる

3.CircleCIで故障が発生しても自分たちで原因解析や復旧をすることが困難
・Saasだから

4.Saasの利用料には要注意
・1コンテナは無料です。詳しくは[こちら](https://circleci.com/ja/pricing/)まで。


## まとめ
ここまで簡単に紹介しましたが、なんとなく便利そうなのは伝わりましたかな？？
実際に使いたいと！思う人はぜひ活用していってください！
素晴らしい記事がありふれているのでいくつか紹介して終わりにしておきます！

[CircleCIホームページ](https://circleci.com/ja/)

[いまさらだけどCircleCIに入門したのでわかりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)

[CircleCIで出来ること](https://qiita.com/noboru_i/items/7d300eb63ae667bf8dc2#%E3%81%8A%E9%87%91%E3%81%8B%E3%81%8B%E3%82%8B%E3%81%AE)

[【使い方】CircleCIとは？EC2にsshしてデプロイ自動化](https://suwaru.tokyo/%E3%80%90%E4%BD%BF%E3%81%84%E6%96%B9%E3%80%91circleci%E3%81%A8%E3%81%AF%EF%BC%9Fec2%E3%81%ABssh%E3%81%97%E3%81%A6%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E8%87%AA%E5%8B%95%E5%8C%96/)

[AWS備忘録８.５～circleCI・EC2にデプロイ～](https://note.com/kinako1525/n/nd20d224607fb)
「多段階選抜」の問題をRubyで解いてみた

### 問題
[第24回オフラインリアルタイムどう書くの問題](https://qiita.com/Nabetani/items/1c83005a854d2c6cbb69)

### 参考 （Clojure 版）

先に Clojure でも解いています。
https://qiita.com/kts_h/items/64bb74fdcef642198bc5

### Ruby 版

すでにRubyによる解答が多数出されているのですが、面白くなって自分でも解いてみたので、貼っておきます。

`solve` の中の `each_char` ブロックを綺麗に書きたかったので、クラスにしてインスタンス変数の中身を次々と変えていくようにしてみました。

```ruby
class MultiStageSelection
  def self.solve(cmds)
    new.solve(cmds)
  end

  def initialize
    @enum = 1.step
  end

  def drop_nth(n)
    enum = @enum
    @enum = Enumerator.new do |y|
      n -= 1
      loop do
        n.times { y << enum.next }
        enum.next
      end
    end
    self
  end

  def drop_before(test)
    enum = @enum
    @enum = Enumerator.new do |y|
      a, b = enum.next, enum.next
      loop do
        y << a unless send(test, b)
        a, b = b, enum.next
      end
    end
    self
  end

  def drop_after(test)
    enum = @enum
    @enum = Enumerator.new do |y|
      a, b = enum.next, enum.next
      y << a
      loop do
        y << b unless send(test, a)
        a, b = b, enum.next
      end
    end
    self
  end

  def drop_100
    enum = @enum
    @enum = Enumerator.new do |y|
      100.times { enum.next }
      loop { y << enum.next }
    end
    self
  end

  def solve(cmds)
    cmds.each_char do |cmd|
      case cmd
      when "s" then drop_before(:square?)
      when "S" then drop_after(:square?)
      when "c" then drop_before(:cube?)
      when "C" then drop_after(:cube?)
      when "h" then drop_100
      else drop_nth(cmd.to_i)
      end
    end
    puts @enum.take(10).join(",")
  end

  private

  def square?(n)
    Math.sqrt(n).truncate**2 == n
  end

  def cube?(n)
    Math.cbrt(n).truncate**3 == n
  end
end


MultiStageSelection.solve("ss6cc24S")
MultiStageSelection.solve("4scC3hh982Cc5s")
```
Power BI パフォーマンスアナライザーでDAX Queryを作成する簡単な方法


## 概要

DAX Queryを作成する簡単な手順として、Power BIのパフォーマンスアナライザーを利用した手順を紹介します。


![image-20200602102811581.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/66f70cff-61ac-3d2d-d45e-dca4b7c99927.png)



Azure Analysis Service、SQL Server Analysis Servicesにライブ接続を実施した際にも、DAX Queryを作成することが可能です。テスト実施時にDAX Queryを作成しておき、DAX Studioから実行すると便利です。



## 手順

①Power BI Desktopにてレポートを開き、"表示"タブの”パフォーマンスアナライザー”を選択。

![image-20200602103111683.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a18d2f31-8fc4-3a64-d426-57be4418112c.png)



②"パフォーマンスアナライザー"ウィンドウにて、"記録の開始"を選択。

![image-20200602103135459.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5fd34be2-80ef-5a37-41dd-aff7b4564b42.png)



③ビジュアルを選択し、"このビジュアルを更新します"を選択。

![image-20200602103223991.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ceea3b8c-e7ab-db73-6430-3ffed7dbf094.png)



④"パフォーマンスアナライザー"ウィンドウに表示されたビジュアル名のペインを開き、"クエリのコピー"を選択。


![image-20200602103334606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2a17d3fc-313c-d310-bbe2-8584cdf9b4a9.png)


⑤ペーストを実施して、DAX Queryを確認。

![image-20200602103459575.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/1f6c2462-974f-5806-0371-24e00d80a144.png)
関数を戻り値とするタイプの高階関数

# 外でも結構されてる説明
を、もう少しわかりやすい命名にしたつもりです。

```python
def k_minus_x(k):
    # もととなる関数。こいつが高階関数。
    def f(x):
        return k - x
    return f

five_minus_x = k_minus_x(5)    # x_minus_3は新しい関数と捉えてOK
print(five_minus_x(3))         # 2

print(k_minus_x(7)(3))         # 4
```


# 真価は場合分けのときなのでは？
試しに書いたのは、じゃんけんするだけのコード。
関数の中で関数を宣言しなくても使えるみたい。
当然もっとシンプルにできるけど、複雑な処理をさせたいときは結構使えそう。

```python
def janken(hand: str):
    # もととなる関数。こいつが高階関数。
    if(hand == 'rock'):
        return print_paper
    elif(hand == 'paper'):
        return print_scissors
    elif(hand == 'scissors'):
        return print_rock


def print_rock():
    print('rock')


def print_paper():
    print('paper')


def print_scissors():
    print('scissors')


print('パターン１。返ってきた関数をそのまま実行する')
janken("rock")()    # paper
janken("paper")()    # scissors
janken("scissors")()    # rock

print('パターン２。一旦新しい関数として保存してから実行する')
show_enemy_hand_against_rock = janken("rock")
show_enemy_hand_against_rock()      # paper

show_enemy_hand_against_paper = janken("paper")
show_enemy_hand_against_paper()     # scissors

show_enemy_hand_against_scissors = janken("scissors")
show_enemy_hand_against_scissors()  # rock
```

>パターン１。返ってきた関数をそのまま実行する
paper
scissors
rock
パターン２。一旦新しい関数として保存してから実行する
paper
scissors
rock

でも毎回このレベルのわけ方してたらだるいなぁ。。。今回のケースなら、returnせずに直接printしちゃう
DHCP

# DHCP
ＤＨＣＰ（Dynamic Host Configuration Protocol）は、ＴＣＰ／ＩＰネットワークにおいてホストに設定情報を伝達するための仕組みです。
ＤＨＣＰはクライアント・サーバ方式で、ＤＨＣＰサーバがネットワークアドレスを動的に割り当て、設定情報とともにホストに送信します。

## DHCPを使う理由
レイヤ３でデータを転送する際に送信先、宛先のアドレス IPアドレス MACアドレスが必要になる。
MACアドレスはNICを元に各デバイスごとに割り振られているがIPアドレスは割り振られていない。
ネットワーク通信を行うためにIPアドレスを取得する必要がある
そこでDHCPを使用することによって、ネットワークに接続した時に自動でIPアドレスを割り振ることができるようになる。

##　DHCPの仕組み

|  |
|:--|:--|
| １． DHCPサーバーを見つける| |
|  ＤＨＣＰクライアントは、ＤＨＣＰサーバを探すためにＤＨＣＰＤＩＳＣＯＶＥＲメッセージをブロードキャストします。 |
| ２． DHCPクライアントを見つける| |
| ＤＨＣＰサーバは、ＤＨＣＰＤＩＳＣＯＶＥＲメッセージの応答として、ＩＰアドレス他の情報を含むＤＨＣＰＯＦＦＥＲメッセージを ダイレクト送信またはブロードキャストします。  |
| ３． DHCPリクエストを送る| |
| 複数のＤＨＣＰサーバが存在する場合、ＤＨＣＰクライアントは複数のＤＨＣＰＯＦＦＥＲメッセージを受信することになります。 ＤＨＣＰクライアントは一つのＤＨＣＰサーバを選択し、ＤＨＣＰＲＥＱＵＥＳＴメッセージをブロードキャストします。  |
| ４． IPアドレスを割り当てる|  |
|ＤＨＣＰＲＥＱＵＥＳＴメッセージを受信したＤＨＣＰサーバは、コンフィグレーション情報を含むＤＨＣＰＡＣＫメッセージを送信します。 ＤＨＣＰＡＣＫメッセージのＩＰアドレスフィールドには、割り当てられたネットワークアドレスが挿入されています。 また、要求されたＩＰアドレスが割り当てられない等、ＤＨＣＰＲＥＱＵＥＳＴメッセージの要求に答えられない場合は、ＤＨＣＰサーバは ＤＨＣＰＮＡＫメッセージを送信します。 |
| ５． IPアドレスをチェック| |
| ＤＨＣＰクライアントは、ＤＨＣＰＡＣＫメッセージを受信するとパラメータの チェックを行い、リース期間などを記録しておきます。ＤＨＣＰＡＣＫメッセージにより受信したコンフィグレーション情報に問題があった場合は、 ＤＨＣＰクライアントはＤＨＣＰＤＥＣＬＩＮＥメッセージを送信します。  |
| ６． ネットワークを解放|  |
|ＤＨＣＰクライアントは、ＤＨＣＰＲＥＬＥＡＳＥメッセージを送信することにより、ネットワークアドレスを解放することができます。|

##
cloud functionで`Error: Request failed with status code 403` のエラーが出る

### 状況
cloud function をhttp型でデプロイして、その関数にアクセスすると、

```
Error: Request failed with status code 403
```
のエラーがはかれる

### 解決策
403 forbidden エラーは、起動の権限がないことで発生するので、権限を付与する。

起動の権限は、コンソール上で行える。この[doc](https://cloud.google.com/functions/docs/securing/managing-access?hl=ja) を参考。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557811/e83df7d5-f3b3-b029-344b-4904b1b0b248.png)
ChromeBook(ChromeOS)の導入のメリット

#まず初めに
これは、特定の商用製品等を推奨、広報するものではない。使用感など評価するものである。
#ChromeBookのメリット
1. 操作がキーボード、タッチパッド、タッチパネルのみで終結できるため、マウスが壊れて使えないことや、マウスを使わなくていいので、荷物を大幅に減らすことができる。
2. シンプルなUI
3. **Googleスプレッドシート**、**Googleスライド**等の無料で**初心者**でも**MS Officeと変わらない使いやすさのあるOfficeソフト**や**Gmail**、**Google App Script**等の機能がフルに使える。
4. 軽い立ち上がり(Core iでなくても使える)
5. 利権と腐敗がない。**淫夢厨**の動画編集による**腐敗**とエロゲ**利権**と**自己責任厨**に使われるWindows。Macは性能も価格も高く[Apple信者](https://appleshinja.com)利権?があるため、PC初心者が手軽に買えそうにない。Linuxはインストールが必要で自由度が高くMacのような手厚いサポートが存在しないため、初心者がつまずく可能性が高い。ChromeBookはプレインストール済み。
6. 一応、**コマンド操作**も対応(最低限の機能であるが、ターミナルを立ち上げることができる)。
7. ChromeOSは色々なハードメーカーが出しており、ソフトウェアの基幹部分で互換OSとなるChromiumOSが**オープンソース**で無料なので、**安く**ハードが**買える**。
8. **Mac並み(又はそれ以上)のお手軽UI**とLinux並みの**安さ**(ただしLinuxのような**自由度はない**)。
9. 安いハードウェアに対応。
10. ウイルスにかかるリスクがほぼ**ない**(特に**[マクロウイルス](https://qiita.com/search?q=%E3%83%9E%E3%82%AF%E3%83%AD%E3%82%A6%E3%82%A4%E3%83%AB%E3%82%B9)**は***ZERO***)
11. マイナーなアプリでなければ**大体存在**します。

#こういう人にオススメ
- PC **初心者**
- Googleのサービスを主に使っている方
- PCの用途が**Officeソフトとブラウジング**を主とする方。
- **コマンド操作をスマホ感覚**でやりたい方
- コンピュータウイルスが**嫌い**な方
- セキュリティを大切にしてる方
- **ショートカットキー**と**タッチパッド**を多用する方
- MacBook買う余裕がない方若しくは、PCに**沢山金を払いたくない**方。
- 安くて**かっこいいPC**が欲しい方
- ノートPCを買いたい方(ChromeBoxってものもありますが、あまりコスパが良いものではないので個人的にはオススメ出来ません)
- ゲームをスマホ(タブレット含む)やゲーム専用機でやる方
- **リモート**で高度な開発をしたい方(カフェで家にあるデスクトップPC(WindowsやiMacやUbuntu等もリモートで動かせます)。
- **[アニメーションpng](https://qiita.com/tags/apng)**や**[Webp](https://qiita.com/tags/webp)**を作る方
- スマホでAndroid OSを使っている方

#逆にオススメできない人
- コマンドを***沢山***使う方(->Linuxを使うのがオススメです。Macでも良い)
- エロゲをやる方(ゲーム自体はAndroidアプリやChromeでのHTMLゲームは可能)
- **アングラ**(アンダーグラウンド)コンテンツに関わる方(**Windows以外難しい**)
- ***高度な***動画編集をやる方(編集がそこそこだとAndroidアプリでできます)
- Android OSが嫌いな方(Chrome OSとAndroid OSの連携はGoogle製OSで非常に良いです)
- Googleのサービスを使わない方
- Google系OfficeアプリやGoogleのサービスが嫌いな方
- 直観的操作が**嫌い**な方
- キーボード(ショートカットキー等)やタッチパッドを使わず、**マウスを多用**する方。
- **1100ドル以上のPC**がどうしても欲しい方
- PCの**自作に拘る**方(性能や拡張性を求めていると思うので、Linux辺り(Ubuntu等)がオススメです)

#PCの使い方リファレンス
Android -> ChromeBook-г->自作PC(Ubuntu,Mint等)
iOS(iPadOS)｣->MacBook｣
このようにして自分でステップアップできます。

#魅力がわかりましたか？
ChromeBookに変えるとこれらの利益があります。是非皆さんも変えてみましょう
第24回オフラインリアルタイムどう書く「多段階選抜」の Clojureによる実装

６年前に出された問題なのですが、面白そうだし、未だに @cielavenir さんが異なる言語で回答を出し続けているようなので、その様子を見て、私もやってみたくなりました。

言語は Uncle Bob が[最近注目](https://blog.cleancoder.com/uncle-bob/2019/08/22/WhyClojure.html)しているらしい Clojure にしてみました。

「多段階選抜」の問題は[ここ](https://qiita.com/Nabetani/items/1c83005a854d2c6cbb69)です。

（改変）`solve-1` で うっかり `solve-1` で再起してしまっていたので、`recur` に改めました。

```clojure
(defn square? [n]
  (let [sq (Math/floor (Math/sqrt n))]
    (== (* sq sq) n)))

(defn cube? [n]
  (let [cb (Math/floor (Math/cbrt n))]
    (== (* cb cb cb) n)))

(defn numbers
  ([] (numbers 1))
  ([n] (lazy-seq (cons n (numbers (inc n))))))

(defn drop-before [test coll]
  (let [f (fn [test coll]
            (let [a (first coll)
                  bs (rest coll)]
              (if (test (first bs))
                (recur test bs)
                (cons a (drop-before test bs)))))]
    (lazy-seq (f test coll))))

(defn drop-after [test coll]
  (lazy-seq
    (let [a (first coll)
          bs (rest coll)]
      (cons a
            (if (test a)
              (drop-after test (rest bs))
              (drop-after test bs))))))

(defn drop-nth [n coll]
  (lazy-cat (take (dec n) coll) (drop-nth n (drop n coll))))

(defn solve-1 [cs coll]
  (if (empty? cs)
    coll
    (let [c (first cs)
          cs (rest cs)]
      (recur
        cs
        (case c
          \s (drop-before square? coll)
          \S (drop-after square? coll)
          \c (drop-before cube? coll)
          \C (drop-after cube? coll)
          \h (drop 100 coll)
          (drop-nth (- (long c) 48) coll))))))

(defn solve [cmds]
  (let [cs (seq cmds)
        ns (numbers)
        answer (->> (solve-1 cs ns)
                    (take 10)
                    (clojure.string/join ","))]
    (println answer)))

(solve "ss6cc24S")
(solve "4scC3hh982Cc5s")
```
python3で定期的に関数を実行する高階関数

6/2,3 しらかみゅさんのアドバイスにより、より短いコードでより正確な動きができるようになりました。

```python:定期的に関数を実行する高階関数
def minute_interval(interval_min: int, at_sec: int, function, *args, **kwargs):
    """RUNS FUNCTION REPETITIVELY
    Args:
        interval_min(int) : Value of minute. If 11, it will operate at 00, 11, 22, 33, 44, and 55.
        at_sec(int) : Value of second. If 5, it will operate at 05.
        function: Function you want to call repetitively
    """
    while True:
        now = datetime.now()

        # when interval_min is 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, or 30
        if now.minute + interval_min < 60:
            wait_min = -now.minute % interval_min
        # when interval_min CANNOT divide 60. e.g: 7,8,9,11,13...
        else:
            wait_min = 60 - now.minute

        now_sec = now.second + (now.microsecond / 1000_000)
        wait_sec = ((wait_min * 60) + (at_sec - now_sec)) % (interval_min * 60)
        print(f'call func after {int(wait_sec/60)} min {wait_sec%60} sec')
        time.sleep(wait_sec)

        function(*args, **kwargs)
```
jQueryを自分なりにまとめた

# 初めに
備忘録です。
## jQueryの概要
### 冒頭
Webアプリなど作っている人には有名な「jQuery」、私は名前しか知らなかったです。。。。
jQueryはWebサイトやWebサービスを作成する上で便利便利な物で、デザインのスキルを向上させたいという人は習得するのがマストだそうです。
### jQueryの大きな特徴
ブラウザの違いを意識せずに済む
HTMLのDOM操作（HTMLの部品を、DOMと呼びます。）が簡単にできる
Ajax処理が簡単に記述できる
### Ajax処理ってなんぞや
Ajaxとは、Asynchronous JavaScript And XML の略です。直訳すると、「非同期（で動作する）JavaScript と XML」です。

## jQueryを使う
### HTMLファイルとリンクさせる
jQueryを使えるようにします。

```html:Test.html
 <script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

```

### HTMLファイルのDOMとリンクさせる(例：テキストボックス)

```html:Test.html
 テキストボックス
<input type="text" id="tBox" class="font-main" />
```

```javascript:main.js
// DOMのidをキーにする場合
 $("#tBox);
```
### Buttonとリンクさせる
ボタンを押下するとアラート表示されます

```html:Test.html
 ボタン
<button type="button" id="btn1">表示</button>
```

```javascript:main.js
// DOMのidをキーにする場合
 $(function(){
 
    // 指定ボタンを押下すると処理を開始する
    $("#btn1").on("click", function() {
      alert('アラートのメッセージ');
    });
   
   
  });
```

# 最後に
jQueryを習得することで、HTMLのDOM操作を簡単に実現できそうです。
コード量を減らさずSwiftファイル数を減らしてビルド速度改善

# 概要

私の担当するアプリはSwiftファイル数がかなり多い(1モジュール内のSwiftファイル数も結構多い)のですが、
必要なコード量はそのままにSwiftファイル数を減らすことでビルド速度改善ができないかと言う話になりました。

# 環境

* Xcode 11.x
* iMac (Quad-Core Intel Core i7 4.2 GHz, メモリ32 GB)



# 先に結論

ビルドするマシンの環境依存の影響もあると思いますが、以下のような結果になりました。
可読性もあるのでそこまでファイル数を減らせていないですが、Swiftファイル数減少に応じて多少ビルド速度改善されました。
(一応複数回計測して平均と取っています)

[削減したSwiftファイル数]
　対応前
　　4325
　対応後
　　3943 (-382)
 
[ビルド時間計測結果(フルビルド)]
　対応前
　　282秒
　対応後
　　276秒 (-6秒程)

# やった施策

## 関連性の強いコードを一つのファイルにする

例えば下記のように特定のファイルに強く依存しているenumを定義しているファイルを

〜Type.swift

```
enum 〜Type {
  ...
}
```

〜Processor.swift

```
class 〜Processor {
  ...
}
```

強く依存している方のファイル内で定義する

〜Processor.swift

```
enum 〜Type {
  ...
}

class 〜Processor {
  ...
}
```

## 短く冗長的なコードを一つにまとめる

短く冗長的なSwiftファイルが複数ある場合

〜Executable.swift

```
public protocol 〜Executable {
  ...
}
```

〜HogeExecuter.swift

```
struct 〜HogeExecuter: 〜Executable {
　(短いコード量)
}
```

〜FugaExecuter.swift

```
struct 〜FugaExecuter: 〜Executable {
　(短いコード量)
}
```

1つのファイルにまとめて定義する

〜Executable.swift

```
public protocol 〜Executable {
  ...
}

struct 〜HogeExecuter: 〜Executable {
　(短いコード量)
}

struct 〜FugaExecuter: 〜Executable {
　(短いコード量)
}
```

# サイズなどが異なるだけの定義を1つのファイルにまとめる

サイズ毎に定義があるがSwiftファイルが分かれているのを

Small〜Entity.swift

```
public class Small〜Entity {
  ...
}
```

Medium〜Entity.swift

```
public class Medium〜Entity: Small〜Entity {
  ...
}
```

Large〜Entity.swift

```
public class Large〜Entity: Medium〜Entity {
  ...
}
```

1つのファイルにまとめました。

〜Entity.swift

```
public class Small〜Entity {
  ...
}

public class Medium〜Entity: Small〜Entity {
  ...
}

public class Large〜Entity: Medium〜Entity {
  ...
}
```