OmniAICreator/Qiita-1.07M huggingface dataset:
i-FILTER×m-FILTER連携時の自動作成パーツについての注意点

検証時のメモ

以下検証環境にて実施

■環境
　i-FILTER Ver.10.20R01-20181016
　m-FILTER Ver.5.11R01-20180802

i-FILTER×m-FILTER連携を有効化すると自動的に以下URLリストと識別名リストが作成される。

*m-FILTER連携URLリスト(完全一致)
*m-FILTER連携URLリスト(部分一致)
*m-FILTER連携デコードリスト(完全一致)
*m-FILTER連携デコードリスト(部分一致)

この4つのパーツだが、参照ロック及び編集ロックが解除されておりどの権限のユーザでも編集ができてしまう。

それを避けるために参照ロック及び編集ロックをするため、ルールパーツの*を外してパーツを保存してしまうとi-FILTER×m-FILTER連携が正常に動作しなくなる。

具体的にはパーツ名を変更してしまうとi-FILTER側はパーツがないため例外処理を返す。
その例外処理が返ってきた場合、m-FILTER側は未カテゴリ扱いをする結果、偽装メール対策機能側で偽装レベル3と強制的に判定される。
つまり偽装メール対策機能をデフォルトで運用している場合、URLがメールのどこかしらに記載がされた場合、そのメールすべてが隔離されてしまう。

困ったことにパーツの編集権限を持ったユーザが誤って変更すると恐ろしいことにURLが記載されたメールがすべてメールが隔離されメール不通状態となる。

マルチテナント的にグループ単位で権限を委譲している環境だと触らないように運用徹底が必要である。

もし変更してしまったことを能動的に知りたい場合はm-FILTERの「i-filter.log」ログから「-19」※の値をひっかけてログ監視をする必要があります。
※「-19」はURLリストがなかった場合のエラーコード

私は最初から触れないようにロックするか、そもそも変更できないようにすべきではないかと思います。(ロックだと全体管理者で設定変更できちゃいますし)
ユーザーってなんでかわからないけど普通ならやらないような設定を平気でやったりする方もいるので...

以上、検証結果でした。
[React][TypeScript]絶対パスでimportできるようにする

## 概要

- create-react-appで作ったTypeScriptプロジェクトで絶対パスでファイルをimportできるようにする

## 手順

### 環境変数の設定

- `.env`に記載するか起動スクリプトに追加する

```:.env
NODE_PATH=.
```

```json:package.json
{
  // ...
  "scripts": {
    "start": "NODE_PATH=. react-scripts start",
    "build": "NODE_PATH=. react-scripts build",
    "test": "NODE_PATH=. react-scripts test",
    // ...
  },
  // ...
}
```

### `tsconfig.paths.json`の作成

```json:tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "src/*": ["*"]
    }
  }
}
```

### `tsconfig.json`へ設定追加

```json:tsconfig.json
{
  // ...
  "extends": "./tsconfig.paths.json",
  // ...
}
```

## 結果

- 以下のように絶対パスでimportできるようになる
- VSCodeに補完もちゃんと効く

```tsx:App.tsx
// ...
import Button from 'src/components/Button'
// ...
```
PHPのiterableとTraversableは違う

PHPの`iterable`型と`Traversable`インターフェイスはどういう性質があるのか？異なる点は何か？どういう関係か？について説明する。

## `iterable`型

* いわゆる疑似型で、`array`もしくは`Traversable`インターフェイスを実装したクラスを指す型。
* `foreach`で反復できる。
* `yield from`のジェネレーター構文が使える。
* PHP7.1で導入された。`Traversable`インターフェイスより新しい。

## `Traversable`インターフェイス

* このインターフェイスを実装したオブジェクトは`foreach`で反復できるようになる。
* 内部エンジンのインターフェイスであるため、PHPコードでこのインターフェイスを直接実装することはできない特殊なインターフェイスである。
* PHP5で追加された。

```php
class SomeClass implements Traversable {}
//=> Fatal error: Class SomeClass must implement interface Traversable as part of either Iterator or IteratorAggregate
```

* 実装できないだけで、型宣言で用いたり、他のインターフェイスが`Traversable`インターフェイスを継承することはできる。

```php
interface SomeInterface extends Traversable {} // ok
$obj instanceof Traversable; // ok
function (Traversable $traversable) {} // ok
```

## `is_iterable()`関数

* 変数の内容が反復可能な値であることを確認する関数。

```php
is_iterable ( mixed $var ) : bool
```

* `iterable`疑似型、つまり、`array`か`Traversable`のとき`true`が返る。

```php
assert(is_iterable([])); // (1) array
assert(is_iterable(new ArrayIterator())); // (2) Traversable
assert(is_iterable((function (): iterable { yield; })())); // (3) Generator
```

ちなみに(3)はジェネレータ構文を使ったクロージャーを呼び出した結果だが、これは`Generator`クラスとして評価される:

```php
$closure = function (): iterable { yield; };
echo get_class($closure()); //=> Generator
```

### そういえば`object`も`foreach`できたよね……？

PHPはオブジェクトも`foreach`で反復することができる。

```php
$obj = new stdClass();
$obj->key1 = null;
foreach ($obj as $k => $v) {
	echo $k, PHP_EOL; //=> key1
}
```

しかし、`is_iterable`関数では`false`になる。

```php
$obj = new stdClass();
$obj->key1 = null;
assert(!is_iterable($obj));
```

## `iterable`と`Traversable`の関係性

* `Traversable`は`iterable`である。
* `array`は`iterable`である。
* `array`は`Traversable`ではない。
* `Generator`は`Traversable`であり、よって`iterable`でもある。
* `**Iterator`は`Traversable`であり、よって`iterable`でもある。
* `Traversable`を実装していないオブジェクトは`iterable`ではない。(foreachで回せるが)

![iterable-2.png](https://qiita-image-store.s3.amazonaws.com/0/889/3b4cd27b-f494-ca8c-a50a-f39321464d12.png)

## 合わせて読みたい

* [PHP: iterable型はiterator_to_array()に渡しちゃいけない - Qiita](https://qiita.com/suin/items/5f76a3eeaca70a5c3ba8)
ITシステムの見積もりの見積もり

ITシステムを見積もる費用の見積もり

ITシステムで、情報のやりとりの規模、情報量などに基づいて見積もる場合の、見積もり費用について見積もってみる。

# 見積もり料金（小規模）
当方では軽微な相談は無料、半日の技術指導料は、実費を除いて12,500円という料金があることを前提とする。

そのため、ITシステムの見積もりをする場合でも、30分程度お話をお聞きして、えいやっと見積もり金額をご提示させていただいたとしても、書類で見積もり金額の積算を出そうとすると、半日仕事になり、見積もりに必要な資料の取得等の費用を合算すると、１０万円でできると見積れるシステムの見積もり費用は2万円程度になります。

# 見積もり料金（大規模）
関係者が100人くらいで、計算機が200台くらいで、情報量が日に1GB以上で、開発が3ヶ月くらいかかり、保守が10年間するようなシステムの見積もりだと、だいたい３日くらいかかり、見積もり費用は約１０万円くらいです。

これが、もし、技術士個人として、おうけした場合は、単価が約１０倍相当であるため、見積もり書類の作成は約100万円程度となると見積もれます。

＜この資料は書き書けです。順次、追記します。＞
#見積もり研究会
NSPICEネットワークという勉強会で、見積もり研究会を仕事場で開催していただいていたことがある。

見積もりの仕方は、規模、分野で様々。

設計ができない人が見積もる場合に、設計ができる人に概算を聞いてから詳細資料を集めるとそれなりに。
設計ができる人に聞かずに見積もると、どうなるかはよくわかっていない。

継続的に仕事をしている顧客の場合は、１回の見積もりの誤差は、何回かの見積もりで吸収できるらしい。

# 調達
官庁の調達では、工業標準化法により、技術的仕様は日本工業規格を尊重することになっている。
しかし、新しい技術では、工業規格が制定される前の技術もある。ISO/IEC, ITU等の国際規格が存在する場合には、WTO/TBT協定にもとづいて、国際規格を尊重することになる。

ソフトウエア開発・調達プロセス改善協議会へ専門委員会から報告をしている。

ソフトウエアプロセスの改善に向けて ~SPIへの今後の取組み~ (ソフトウエア開発・調達プロセス改善協議会報告書の公表)
http://warp.da.ndl.go.jp/info:ndljp/pid/1368617/www.meti.go.jp/kohosys/press/0002639/0/020419spi.pdf

# 参考資料(reference)
自動車産業におけるソフトウェア製品の出荷額の見積もりと改善の方向性
https://researchmap.jp/joulazjos-50024/

情報システムに係る政府調達の見直しについて ~ソフトウェアの特質を踏まえた政府調達制度の改善に向けて~
http://dl.ndl.go.jp/view/download/digidepo_1285959_po_011226infomationsystem-hontai.pdf?itemId=info%3Andljp%2Fpid%2F1285959&contentNo=1&alternativeNo=&__lang=ja

日本政府の取組み
総務省行政管理局(CIO連絡会議事務局) 課長補佐 斎藤宏海氏
http://www.nmda.or.jp/nmda/tech-report/report14/pdf-file/03-10.pdf

2007年
i 経済産業省委託平成１９年度産業技術研究開発委託費（基準認証研究開発事業：情報分野の国際競争力強化の標準化調査研究）ソフトウェアの評価技術の標準化 に関する調査研究 
https://manualzz.com/doc/4833215/ソフトウェアの評価技術の標準化に関する調査研究-pdfﾌｧｲﾙ約1005kb-

工業標準の制定・日本工業規格の改正に関する説明資料 
https://updoc.site/download/5b3c5572d3e67_pdf

# 文書履歴(document history)
ver. 0.01 初稿 20190212 午前
ver. 0.02 参考URL追記 20190212 午後

### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
AWS でネットワークインターフェースの削除で You do not have permission to access the specified resource. が出てエラーになる

権限がないというエラーメッセージだが、IAMは関係ない。
NATゲートウェイやElastic IP等のそのIPに紐付いているリソースを先に削除した後に、
その Elastip IP を解放すれば良い。
Node.js: process.exitを呼ぶとloggerでファイルが出力されない

# 環境
* Node.js v10.13.0
* log4js: 3.0.6
* ECMAScript6


# やりたいこと
log4jsを使って、ファイルとコンソールにログを出力したいです。

```javascript

// logger設定
const logger = initialLogger();
logger.debug("start");

// *** 終了であることを示すため、以下の文を追加してしまった ***
process.exit(0);

/**
 * loggerの初期化
 */
function initialLogger() {
    const log4js = require("log4js");
    const logFilePath = "test-log.txt";
    const patternForFile = "[%d{ISO8601_WITH_TZ_OFFSET}] %h %p %c: %m";
    const patternForConsole = `%[${patternForFile}%]`;
    log4js.configure(
        {
            appenders: {
                outConsole: { type: "console", layout: {type:"pattern", pattern: patternForConsole} },
                outFile: { type: "datefile", filename: logFilePath, layout: {type:"pattern", pattern: patternForFile} },
            },
            categories: {
                default: { appenders: ["outConsole", "outFile"], level: "debug" },
            },

        });
    const logger = log4js.getLogger();
    logger.level = "debug";

    return logger;

}
```

# 問題

`node test.js`で実行すると、コンソールには以下の内容が出力されましたが、`test-log.txt`には出力されていませんでした。

```
[2019-02-12T11:10:58.691+0900] DESKTOP-41K65S9 DEBUG default: start
```

# 原因
`process.exit`は非同期処理を待ってくれないから。

### 参考サイト
https://takamints.hatenablog.jp/entry/dont-invoke-the-process-exit-on-success
http://neos21.hatenablog.com/entry/2017/11/24/080000


# 備考
コンソールには出力されていたので、原因調査に少し時間がかかりました。
Windows:日本語IMEを殺してGoogle日本語入力だけで快適に生きていく

Google日本語入力はすばらしい。辞書がクラウドにあるので、自宅ではMacを使っていても、両方同じユーザー辞書を育てることができる。WindowsではWSL＞Ubuntu＞Emacsを使っているのだが、こちらもmozcでGoogle日本語入力を使っている。
Google日本語入力は他のユーザーの集合知（集合愚？）も生かされていて、リア充と入れると爆発しろと予測変換される。便利だ。

WindowsにGoogle日本語入力をインストールしても、デフォルトのWindows純正日本語IMEは消えてくれない。邪魔だ。消えてくれ。

そこで消す方法である。
いろいろなブログに書いているが、ぼくなりの最小限の手順を紹介したい。
~~これはコルタナくんから検索するのが早い。コルタナくんはスタートボタンの横の○がついたボックスのようなもので、iPhoneのSiri、Excelのカイル君のようなものだ。ぼくはこれをツールバーの設定からボックスは消して○だけ残して使っている。~~

（2019-10-24変更）
これはスタートボタン（田ボタン）の右にある検索ボックス（虫眼鏡アイコン🔎）から行くのが速い。昔はコルタナ○でも単純な検索が出来たが、コルタナと虫眼鏡🔎に分かれたようだ。コルタナ○は使い所が分からないから抹消した。

Windowsキー＋Sで何かを入力するモードになる。Searchの略であるから覚えやすい。ここで「言語」と入力すると、「言語の設定」が表示されるのでクリックする。

すると、言語＞優先する言語の中に「日本語」という言語がある。
クリックすると「オプション」という表示が出てくる。

すると、「キーボード」の項目にGoogle日本語入力と並んで、にっくき日本語IMEが並んでいるので、これをクリックする。削除ボタンが表示されるので、クリックする。

あとはボックスを全部閉じれば使えるはずだ。

外国人向けにマニュアルを執筆していて、スクショを取る関係でUIを英語にしたい場合がある。この場合も同じ「言語」設定画面で、「英語」言語を選択し、Windowsの表示言語を「英語（United States）」などに変更する。
ログアウトしてログインすると英語になる。

この場合もIMEに、Google日本語入力の他に「ENG」という英語しか入力できないやつが出てきてやっかいだ。
これも、上記の手順で削除できる。

英文を書くときもGoogle日本語入力を使ってできるし、あやふやな単語は予測変換してくれるしU+XXXXでUnicodeが変換でき、たとえばU+00E9でPokémon Goのアクサンテギュつきeが出てきたりして便利だ。

2024-01-07追記：

ある日、急にMS IMEが追加され、しかも、上記の方法で消せない現象があった。
具体的に言うと「オプション」の選択肢にMS IMEが出なくなる。
試行錯誤したが、この場合、いったんMS IMEをあえて追加して、それを改めて削除すると直った。
なんのつもりだ＞Microsoft
Angularで:host {position: sticky } が効かないのを解消する方法

Angularで:host に対してposition: stickyを指定しても効いてくれなくて困っていました。

[stackoverflow](https://stackoverflow.com/questions/43707076/position-sticky-not-working-css-and-html)によるとなぜかdisplay: blockを加えることで解消するようです。

あとtopなどの明示も忘れずに。

```css
:host {
  display: block;
  top: 0;
  position: sticky;
  position: -webkit-sticky;
}

```
salesforce キュー覚書

キューに割り当てたユーザにメールを送信しようとしたとき。

### 用語
- メンバーへのメールの送信：キューに設定したメールアドレスに送るのか、キューに割り当てたユーザのアドレスに個別に送るのか設定できるチェックボックス。

### 事例を検討
|チェックありの場合|ユーザ割当有|ユーザ割当無|
|:--|--:|--:|
|キューのメールアドレス有|両方に送信|キューのみ送信|
|キューのメールアドレス無|ユーザのみ送信|送信なし|

|チェックなしの場合|ユーザ割当有|ユーザ割当無|
|:--|--:|--:|
|キューのメールアドレス有|キューのみ送信|*キューのみ送信*|
|キューのメールアドレス無|ユーザのみ送信|送信なし|

### 注意点
キューの「メンバーへのメール送信」にチェックがないときはキューに設定したメアドにのみ送信され、チェックがあるときはキューに設定したメアドと割り当てたユーザのメアド両方に送信される。
しかし、「メンバーへのメール送信」にチェックがなくてもキューにメアドが設定されていないときは、割り当てたユーザにメールが送信される。
この”気の利いた”仕様は予測しづらい仕様なので、覚えておくとどこかで困らずに済むかも。
tmuxでセッションが復元しない時の対応

tmuxでtmux-ressrrectで自動保存してくれるtpmがあるのに
再起動しても復元されない場合、以下のコマンドを実行します。

```
cd ~/.tmux/resurrect
ln -sf tmux_resurrect_<最新日時> last
```

これでtmuxを開いてPrefix + C-rで復元できる。

なんで復元できないかはまた調べます。

## 軽く解説
tmux-ressrrectが設定されている場合はデフォルトで60分ごとに~/.tmux/ressurect配下にtxt形式でログが残ります。

さらに最新のログはlastファイルにシンボリックリンクされている状況になります。
本来であれば再起動後、tmuxはこのlastを読みにいって復元するのですが、
それがうまいことリンクが貼れていないと復元できません。

そのため、上のコマンドを実行してリンクを張り直します。
ワークフロールール　時間ベースのアクション覚書

キューに貯まったジョブが実行されるのが15分おきなので検証が面倒でした。

# 用語
- 時間ベースのアクション：今回検証するもの。ワークフロールールに追加できるアクション。日付か時間を設定して「○日前」「○時間後」のようなアクションを可能にする。
- 評価条件：ラジオボタンで選択できる。こっちを評価してからルール条件が評価される。
- ルール条件：カスタマイズできる。評価条件を通過してから評価される。

評価条件を満たしたときにルール条件に一致しているか確認し、一致していたらワークフローアクションを実行するという流れ。
 
# 仕様
### メール通知タイミング
日付項目(Date__c)を作成する。
15日前になったらメールを通知する時間ベースのアクションをワークフロールールに追加する。
Date__cに...
①過去日付を入力すると、即時メール通知される。
②15日以内の日付を入力すると、即時メール通知される。
③15日以降の日付を入力すると、日付が変わって15日前になった瞬間にメール通知される。

### メールが送られるタイミング
「時間ベースのアクションは個別には実行されません。最初のアクションがバッチに入ってから 1 時間以内に実行が開始される、1 つのバッチにグループ化されます。」
このバッチが実行されるのは15分おき。
①②のように即時メール通知される場合、厳密には0分、15分、30分、45分までに溜まったメールを一斉送信している。
③の場合は、日付が変わった0:00ちょうどにメールを送信する。

### 日付項目
日付項目の時分秒はすべて00:00:00。
この項目を参照して時間ベースのアクションを作成すれば、例えば前日の正午(12時間前)や15日前の午後15時(345時間前)といった通知タイミングの調整ができる。なお入力できる数値は整数のみなので、例えば2時間半前(2.5時間前)といった指定はできない。

### タイムトリガを有するワークフロールールの機能制限
「レコードが次の場合にルールを評価 作成されたとき、および編集されるたび」を評価条件に指定することができない。
つまり、「作成されたとき」「作成されたとき、およびその後基準を満たすように編集されたとき」のみ。
これが意味するのは、項目が変更されるたびに評価しなおすことはないということ。一度評価されてしまうと2度目はない。
例えば...
レコードに紐づく担当者に、期日が迫ったらメールを通知するとする。
期日が迫ってメールが送信されてから担当者を変更しても、変更先にメールを通知することはできない。
また、期日が迫ってメールが通知されてから期日を延ばしても2度目のアラートは来ない。
ルール条件に「isChanged」を使って項目変更をチェックしたところで、それ以前に評価条件がtrueのままならルール条件まで辿り着けないので無意味。

### 機能制限を踏まえて
「作成されたとき、およびその後基準を満たすように編集されたとき」にしたとき。
例えば...
レコードを自動で作成して後から編集した項目に関するメールが飛ぶようにしたいとする。
自動作成時に評価条件が満たされてしまうと、あとから何をやっても評価しなおされることはない。

# 変更セット
### ワークフロールールの移行
タイムとリガを有するワークフロールールは、移行先で一度でも動かしてしまうと変更セット検証時にエラーになってしまいます。
設定から[環境]＞[監視]＞[時間ベースのワークフロー]で一覧できるキューから未実行のワークフローを削除しても同様です。
移行元で一度ワークフロールールを無効化して送信し、移行先で有効化すればいけます。

# まとめ
タイムトリガを使うことが分かっている項目は日付型の通知タイミングの柔軟性が高いことや、一度通知が飛んだレコードを変更しても2度目の通知は飛ばないといったことを設計前に把握しておけば後悔が減りそう。
composerでタイムアウトが発生する問題

composerのタイムアウトはデフォルトで300秒になっています。

```
$ composer start
> php -f example.php
                                                                              
  [Symfony\Component\Process\Exception\ProcessTimedOutException]              
  The process "php -f example.php" exceeded the timeout of 300 seconds.  
                                                                              

start [--dev] [--no-dev] [--] [<args>]...
```

composer.jsonに以下の設定を追記することで、タイムアウトの秒数を変更できます。

```composer.json
"config": {
    "process-timeout": 0
},
```

※ 0にすると無制限です。
GAE/Goでデプロイ先によってapp.yamlを切り替える

GAE/Goで開発をしている際、GCPプロジェクトを本番用と開発用を作り、それぞれ別のapp.yamlを用いてデプロイしたい状況になった。
もう少し詳しく書くと、app.yamlファイルからincludeするyamlファイルを環境によって切り替えたくなった。なので、app.yamlを２つ用意してデプロイ時にapp.yamlを切り替えるという方法をとった。

# プロジェクト構成

まず、プロジェクト内で本番用のディレクトリ(prod)と開発用のディレクトリ（dev）を作成する。
その中に

```terminal
prod
 |- main.go
 |- app.yaml
 |- prod.yaml
 |- firebase_config.json

dev
 |- main.go
 |- app.yaml
 |- dev.yaml
 |- firebase_config.json

Makefile
```

こんな感じで
`main.go ⇨ 最初に実行されるファイル
app.yaml ⇨ デプロイに関する設定を記述しているファイル
prod(dev).yaml ⇨ app.yamlからincludeされるファイル
firebase_config.json ⇨ prod(dev).yamlから読み込まれるfirebaseの設定ファイルなど`
を置く。

また、プロジェクトのルートに
`Makefile`
を置く。

# app.yaml

app.yamlはこんな感じ

```app.yaml
runtime: go
api_version: go1.9
env: standard
threadsafe: true
instance_class: F1

includes:
- prod.yaml

handlers:
- url: /.*
  script: _go_app
  secure: always
  redirect_http_response_code: 301
```

それぞれの環境にあったyamlファイル（上記の場合はprod.yaml）をincludeする。

# prod(dev).yaml

prod(dev).yamlはこんな感じ。

```prod.yaml
env_variables:
  SECRET_PROJECT_ID: #プロジェクトID
  CREDENTIALS: #firebaseの設定ファイルパス
```

# main.go

main.goはこんな感じです。

```main.go
package main

import (
	"xxxxx/backend/infrastructure"

	"google.golang.org/appengine"
)

func main() {
	infrastructure.RegisterHandlers()
	appengine.Main()
}
```
ルーティングを呼び出してます。

main.goは本番用も開発用も同じです。
切り替えるのはapp.yamlでincludeするyamlファイルです。

で、デプロイを冗長なコマンドでやっててもアレなんでMakefileでまとめておきます。

```text
VER="deploy-version"

prod:
	gcloud config set project プロジェクトID
	goapp deploy -application プロジェクトID -version $(VER) ./deploy/app.yaml

dev:
	gcloud config set project プロジェクトID
	goapp deploy -application プロジェクトID -version $(VER) ./dev/app.yaml
```

下のコマンドでデプロイできます。

```terminal
$ make prod VER=release
```

本番用なら `make prod` 開発用なら `make dev` です。
`VER`でデプロイするバージョンを指定できます。
Railsでジェネレート時に不要なファイルを生成しない

`config/initializers/generators.rb` に

```sh
Rails.application.config.generators do |g|
  # ヘルパーを生成しない
  g.helper false
  # CSS, JavaScriptファイルを生成しない
  g.assets false
  # config/routes.rbを変更しない
  g.skip_routes true
  # テストスクリプトを生成しない
  g.test_framework false
end
```
concrete5 のアップデートで失敗してしまったときの対処法


アップグレードスクリプトのバグとアップグレード時の処理がタイム・アウトしてしまった可能性が考えられます。

# バグの場合

バグであればどういう条件でこのバグが発生するか、concrete5 を新規でインストールしてからの変更がどのようなものかを検証し、再現する必要があります。

普段のアップデートでは問題が無いので、何か多くの方が行っていない concrete5 の設定の変更などがバグのトリガーになっていると思います。

どの設定を変更したからアップデートを失敗してしまったか、というのを再現手順のステップと concrete5 の GitHub か日本語フォーラムで報告してもらえば、治せるかどうか確認してくれると思います。

# アップグレードタイムアウトの場合

アップグレード時の処理がタイム・アウトされてしまった可能性について説明します。

まず、ブラウザではなく、SSH から concrete5 の CLI を使ってアップデートを試み、成功すればタイムアウトが原因です。

PHP の max_execution_time が小さいと、これらのアップデートの時間が足りなくなり、ブラウザだと、最後までアップデートが走らない場合があります。

## CLI でのアップデートの方法

/[c5 までのパス]/concrete/bin/concrete5 c5:update コマンドでアップデートをします。それがダメであれば --rerun オプションを使って、アップデート再度走らせます。 --after オプションを使うことで、アップデート前のバージョンを正しく指定してアップデートのスクリプトをすべて走らせることが可能です。

例
```
concrete/bin/concrete5 c5:update --rerun --after=8.2.1
```

サーバーが apache や nginx ユーザーとして実行している場合は
sudo -u apache か
sudo -u nginx を
つけて実行する必要があります。

## 開発者向けの参考情報

アップグレードの際、concrete5 では Migration スクリプトを走らせています。

concrete5 過去のバージョンからアップデートする際 concrete5 内で変更がある場合があります。データベースの構造が変わったり、管理画面のページが増えたり、デフォルトのページ属性が増えたりします。

それらの変更が各バージョンごとに、バージョンがリリースされた日付で変更を適用する PHP スクリプトが入っています。

参考までにそのスクリプトの場所は
```
/concrete/src/Uddater/Migrations/Migrations/
```
配下です。
AlienwareでSCPを正常に使う方法

#AlienwareでSCPを正常に使う方法
Alienwareを機械学習や3DCGソフトの用途で利用している方もいらっしゃると思いますが
SCPやGoogleリモートデスクトップが正常に使えずはまったのでメモしておきます。

##Killer Control Centerの設定画面で【Advanced Stream Detect】をオフにする
サポートに相談したところ、上記で解決しました。
ついでにKiller Network Serviceも不要そうなのでmsconfigで切っておいた。
Mojaveでローカル環境でApacheを動かす

# これは何？
macOSがVersionアップ時にほとんど起こるApacheの設定変更のメモです。

# 注意
- **Mojave**向けなので、他のバージョンで以下の設定をして動作を保証するものではありません。
- 設定時は**super user**権限で行うので、権限があるかどうか事前の確認を行ってください。
- この設定は個人の**開発環境用の設定**で、一般公開用の設定ではありません。

# 方針
- ウェブサーバをmacOSに同梱されているapacheで動作させる
- ユーザディレクトリを有効化し、`~/{user_name}/Sites/`以下をユーザのDocumentRootとする  
- HTTP/2を有効にする
- mod_rewriteを有効にする
- 公開ディレクトリ内のディレクトリ表示、シンボリックリンク、Multiviewを有効にする
- ミドルウェア動作の設定は行わない（例：PHP, Perl等）
- VirtualHostの設定は行わない

# 設定を行う

## `/etc/apache2/httpd.conf`の修正

- 以下を有効化
- 有効化するには、行頭の`#`を削除する

```apache
LoadModule http2_module libexec/apache2/mod_http2.so
```

```apache
LoadModule userdir_module libexec/apache2/mod_userdir.so
```

```apache
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
```

```apache
Include /private/etc/apache2/extra/httpd-userdir.conf
```
（↑ `/etc/apache2/extra/httpd-userdir.conf`が読み込まれるようになる）


## `/etc/apache2/extra/httpd-userdir.conf`の修正

```apache
Include /private/etc/apache2/users/*.conf
```
（↑ `/etc/apache2/users/{user_name}.conf`が読み込まれるようになる）

## `/etc/apache2/users/{user_name}.conf` を修正
```apache
<Directory "/Users/{user_name}/Sites/">
  Options Indexes MultiViews FollowSymLinks
  Require all granted
</Directory>
```

-  `{user_name}`には`/Users/`に存在するユーザ名を使用する。
- 一行目の`<Directory "/Users/{user_name}/Sites/">`内の`Sites`を変更することでDocumentRootを変更することが可能。

## ディレクトリの作成
ユーザ名：{user_name} のユーザディレクトリを作成する。

```shell
$ mkdir -p /User/{user_name}/Sites
```

# apacheを起動

```shell
$ sudo /usr/sbin/apachectl restart;
```

# 動作確認
以下の2点で動作確認
- ブラウザのアドレスバーに`127.0.0.1`と入力して`It works!`と表示される
- ブラウザのアドレスバーに`127.0.0.1/~{user_name}/`と入力して`/User/{user_name}/Sites`のファイル一覧が表示される

# その他
## 設定できてるはずなのに動かない
正しい使い方であるかは調べていませんが、以下のようにオプションなしでコマンドを実行すると、エラー表示がされることがあります。

```shell
$sudo /usr/sbin/apachectl;
```
## ログの確認
ログは以下の2つです。
- `/var/log/apache2/error_log`：エラーのログが書き込まれるファイル
- `/var/log/apache2/access_log`：アクセスのログが書き込まれるファイル

### `error_log`
`/etc/apache2/httpd.conf`の以下を書き換えることでファイル名の変更が可能です。

```apache
ErrorLog "/private/var/log/apache2/error_log"
```

### `access_log`
`error_log`と同様に`/etc/apache2/httpd.conf`の以下を書き換えることでファイル名の変更が可能です。

```apache
CustomLog "/private/var/log/apache2/access_log" common
```


# Reference
- [High Sierraでローカル環境（Apacheのバーチャルホスト）が動かなくなったときの対応](https://qiita.com/naoyago/items/ded0aabb3d77721b654d)
Node.jsでES Modules（export/import）ができなかったので軽く調べた

# 概要

Node.jsでES Modulesを試そうとした時に、SyntaxErrorを吐いたのでちょっと調べてみました。

# 結論

.jsを.mjsにしてnodeでjsを実行する時に`--experimental-modules`パラメータを与えるとES Moduleが使える。

# コード

```js
// app.js
import {
    log1,
    log2
} from './ex';
import {
    hoge
} from './class';
log1();
log2();
const obj = new hoge();
obj.say();
```

```js
// ex.js
export function log1() {
    console.log('log1');
}
export function log2() {
    console.log('log2');
}
```

```js
// class.js
export class hoge {
    say() {
        console.log('hoge->say()');
    }
}
```

# 実行結果

```
~/D/t/jsTest> node app.js
/Users/s-yoshida/Downloads/temp/jsTest/app.js:1
(function (exports, require, module, __filename, __dirname) { import {
                                                                     ^

SyntaxError: Unexpected token {
    at new Script (vm.js:83:7)
    at createScript (vm.js:267:10)
    at Object.runInThisContext (vm.js:319:10)
    at Module._compile (internal/modules/cjs/loader.js:684:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
    at Function.Module._load (internal/modules/cjs/loader.js:552:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:774:12)
    at executeUserCode (internal/bootstrap/node.js:342:17)
```

import？何それ？オイシイノ？と仰ってる(´・ω・｀)

# 調べる

「`node` `es` `module`」でググると公式が出てくるので眺める。
[ECMAScript Modules | Node.js v11.9.0 Documentation](https://nodejs.org/api/esm.html)の[Enabling](https://nodejs.org/api/esm.html#esm_enabling)のところに、

```
The --experimental-modules flag can be used to enable features for loading ESM modules.
Once this has been set, files ending with .mjs will be able to be loaded as ES Modules.
```

と書いてある...要約すると「`--experimental-modules`フラグを指定するとES Moduleが有効になるよ」「.mjsファイルをES Modulesとしてロードできるよ」とのこと。なるほど。

# 手直しして動かす

.jsを.mjsに修正して動かす。

```
~/D/t/jsTest> node --experimental-modules app.mjs
(node:53346) ExperimentalWarning: The ESM module loader is experimental.
log1
log2
hoge->say()
```

やったぜ(๑•̀ㅂ•́)و✧
Firebase環境構築メモ (using Carthage)

## What

Carthageを使ってFirebase (今回はその中のFirebaseAnalyticsとFirebaseFirestore) を使用するプロジェクトをビルドするのに少し手間取ったので、その際に必要だった作業のメモです。

## Goal

今回はFireStoreが使いたかったので、以下の2つのビルドが成功した時点をゴールとします。

- FirebaseAnalytics
- FirebaseFirestore

## Environments

- MacOS 10.14
- Xcode 10.1
- Carthage 0.31.2

## How

基本的に[オフィシャルのGithub Repositoryに置かれているドキュメント](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)を読んでそのとおりに実行します。

### Cartfile

まずCartfileに以下を追記して `carthage update` を実行します。

```:Cartfile
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFirestoreBinary.json"
```

### Link Binary With Libraries

上記手順で `Carthage/Build/iOS/` に生成された `*.framework` を `Link Binary With Libraries` に追加します。

私の場合は以下のようなファイルでした。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18007/3aac65ed-331e-b5aa-07af-45e5f92f5b85.png)

### Other Linker Flags

"Other Linker Flags" in "Build Settings" に `-ObjC` が設定されていない人はしておきます。

![Pasted_Image_2019_02_12_2_32.png](https://qiita-image-store.s3.amazonaws.com/0/18007/c4831f13-c967-bd92-571c-2e1d567af7fc.png)

### Import GoogleService-Info.plist

[Firebase console](https://console.firebase.google.com)から `GoogleService-Info.plist` を取得していない人は取得してプロジェクトにインポートしておいてください。

### Remove Firebase.framework

ここで `Firebase.framework` を `Link Binary With Libraries` から削除してください（そもそも上の手順で入れなければ良さそう）。

理由については[こちらのgithub issue上のコメント](https://github.com/firebase/firebase-ios-sdk/issues/911#issuecomment-372455235)にあります。

### Import Bundle

ここで必要に応じて "Copy Bundle Resources" in "Build Phase" にリソースファイルを追加します。

今回の手順ではFirebaseFirestoreを使用しているので `Carthage/Build/iOS/FirebaseFirestore.framework/gRPCCertificates.bundle` が必要です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18007/876d4d98-482d-0776-9464-5507f144c65e.png)

### Link Dependent Libraries

さて[オフィシャルの手順書](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)的にはこれでほぼ終わったも同然なのですが、最後の

> Some additional libraries/frameworks may be needed depending on which Firebase frameworks you use

が曲者です。何が必要なのかなんとなく分かるけど、トライアンドエラーが必要。

というわけでビルドを試して出てきたエラーログと格闘した結果今回使うFirebase frameworksが依存していたのは以下の3つだったので、これらを `Link Binary With Libraries` に入れることで無事ビルドすることができました。FirebaseAnalyticsに値が送られていることも確認できたので無事動いているようです。

- libsqlite3.tbd
- libc++.tbd
- StoreKit.framework

## まとめ

CocoaPodsを使えばもうちょっと簡単にできるのですが、将来的なものとかCI環境とかを考えるとできるだけCarthageに寄せていきたい気持ちなので、多少の頑張りで解決できる部分は対応していきたい。

## References

- [firebase-ios-sdk/Carthage.md at master · firebase/firebase-ios-sdk](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)
- [ios - What is MeasurementNanoPB.framework for? - Stack Overflow](https://stackoverflow.com/questions/52501877/what-is-measurementnanopb-framework-for)
- [[iOS]げにCarthageでFirebase管理は世知辛い Analytics導入時のビルドエラー殲滅していく(Xcode10.0対応版) - Qiita](https://qiita.com/crea/items/9fb7bcd62ab0ab405622)
- [Cloud Firestore iOS SDKをCarthageで組み込むとクラッシュするあなたへ - tofucodes diary](http://tofucodes.hatenablog.jp/entry/2018/08/22/232543)
【Swift4】CIFilterでUIViewをモノクロのUIImageにする

# はじめに
UIViewをモノクロにしたUIImageを出力する実装をしてみました。
以下のOSSを大変参考にさせていただきました。
https://github.com/freshking/BKFilterView

# 実装
考え方は簡単で、UIViewをUIImageにし、CIFilterで彩度をいじるだけです。
以下のような画面でサンプル実装しました。
BaseView：画面上部の赤いUIView
ImageView：画面下部のモノクロImageを表示するUIImageView
<img width="300" alt="sample.png" src="https://qiita-image-store.s3.amazonaws.com/0/110630/c838bb01-3ff6-05e7-d6a3-c71a19337abc.png">


```swift:ボタン押下時に実装したフィルター処理
// 画面におけるBaseViewの部分を切り取り描画する
var screenshot: UIImage?
UIGraphicsBeginImageContextWithOptions(self.baseView.frame.size, false, UIScreen.main.scale)
if let imageContext = UIGraphicsGetCurrentContext() {
    imageContext.translateBy(x: -self.view.frame.origin.x, y: -self.view.frame.origin.y)
    self.baseView.layer.render(in: imageContext)
    screenshot = UIGraphicsGetImageFromCurrentImageContext()
}
screenshot = UIGraphicsGetImageFromCurrentImageContext()

screenshot?.draw(in: self.baseView.frame)

// 描画したContextを取得し、Filterをかける。
guard let context = UIGraphicsGetCurrentContext(),
    let originalImage = context.makeImage(),
    let bwFilter = CIFilter(name: "CIColorControls") else {
        return UIGraphicsEndImageContext()
}

let ciImage = CIImage(cgImage: originalImage)
bwFilter.setValue(ciImage, forKey: kCIInputImageKey)
// 彩度を下げる
bwFilter.setValue(NSNumber(value: 0.0), forKey: kCIInputSaturationKey)

// Contextにフィルターをかけ、UIImageを描画する。
if let bwFilterOutput = bwFilter.outputImage {
    let outputImage: UIImage = UIImage(ciImage: bwFilterOutput)
    outputImage.draw(in: self.baseView.frame)
    
    self.imageView.image = outputImage
}
UIGraphicsEndImageContext()
```

# おわりに
あまり使うことはないかもしれませんが、いつか誰かの参考になれば！
以下にソースコード全体をアップロードしております。
https://github.com/y-negi/UIViewFilteredImage
Azure仮想マシンのIPアドレス一覧をAPIで取得

# 概要
Azure上の仮想マシンは、Web APIで一覧を取得できます。
Azureにデプロイしたシステムと、Azure外の社内システムなんかを連携させたい場合なんかは、このAPIで取得したIPのみ社内システムに許可させるとかできます。
ウチでは、Azure Functionsからのリクエストを社内システムに通すために、これを使っています。

# リクエスト方法
↓にPOSTします。
https://azuredcip.azurewebsites.net/api/azuredcipranges

bodyには、JSONで条件を指定します。
条件の指定方法は後述。とりあえずcurlするとこんな感じ(Windowsでもcurlできるようになったよ!)。

```
curl -X POST -H "Content-Type: application/json" -d "{'region':'all', 'request':'dcip'}" https://azuredcip.azurewebsites.net/api/azuredcipranges
```

## 全IPの一覧
とりあえず、手っ取り早くIPの一覧を得るには、bodyに下記を指定してください。

```json
{"region":"all", "request":"dcip"}
```
regionごとに、CIDR表記でIPの一覧が返ってきます。

```json
{
  "uswest" : [
    "13.64.0.0/16",
    "13.73.32.0/19",
    "13.83.0.0/16",
    "13.86.128.0/17",
    "13.87.128.0/17",
    "13.88.0.0/17",
    "13.88.128.0/18",
    "13.88.192.0/23",
  :
```

## regionの一覧

regionの一覧が欲しい場合は、下記。
regionパラメータは指定しても良いですが、無視されます。

```json
{"request":"dcnames"}
```

結果。

```json
[
  "australiac2",
  "australiac",
  "australiaeast",
  "australiasoutheast",
  "brazilsouth",
  "canadacentral",
  "canadaeast",
  "indiacentral",
  "uscentraleuap",
  "uscentral",
  "asiaeast",
  "europeeast",
  "useast2euap",
  "useast2",
   :
```

## regionごとの一覧
特定のregionについてのIPが欲しければ、regionパラメータに指定します。

```json
{"region":"japaneast", "request":"dcip"}
```

結果。

```json
{
  "japaneast" : [
    "13.71.128.0/19",
    "13.73.0.0/19",
    "13.78.0.0/17",
    "20.37.96.0/19",
    "20.38.116.0/23",
   :
```

# 参考になったサイト
[Azure: Get Datacenter IP address ranges via API](https://social.technet.microsoft.com/wiki/contents/articles/50886.azure-get-datacenter-ip-address-ranges-via-api.aspx)
Excel2013 環境設定

## Excelのオプション（「ファイル」＞「オプション」）

- 「基本設定」＞「起動時の設定」＞「このアプリケーションの起動時に～」をチェックオフ

- 「基本設定」＞「新しいブックの作成時」＞「ブックのシート数」を「1」に設定

- 「文章校正」＞「オートコレクトのオプション」ボタン ＞

    - 「オートコレクト」タブ ＞ 全てチェックオフ

    - 「入力オートフォーマット」タブ ＞「インターネットとネットワークのアドレスをハイパーリンクに変更する」をチェックオフ
    
- 「数式」＞「エラーチェック」＞「バックグラウンドでエラーチェックを行う」をチェックオフ

- 「詳細設定」＞「編集設定」＞「オートコンプリートを使用する」をチェックオフ ※上のセルで入力した内容が候補で表示される機能

- 「詳細設定」＞「切り取り、コピー、貼り付け」＞「コンテンツを張り付けるときに～」をチェックオフ

- 「詳細設定」＞「表示」＞「ハードウェア グラフィック アクセラレータを無効にする」をチェックオン

- 「リボンのユーザー設定」＞右側ペインの「開発」をチェックオン

<br>

# Personal.xlsbを配置
```
C:\Users\<ユーザープロファイルフォルダ名>\AppData\Roaming\Microsoft\Excel\XLSTART
```
自分のSpringBootプロジェクト環境を仲間に渡そう

STS環境とそれに紐づくMySQL環境を出来るだけ簡単かつ確実に渡せる方法はないかなと試行錯誤してみました。

というわけで、こんな感じに動かせるCRUDサンプルを仲間に渡したいと思います。


![crud_demo.gif](https://qiita-image-store.s3.amazonaws.com/0/27090/3b96ed18-51fa-a63b-7f25-3cde3d5338a9.gif)


----

## 前提条件

以下の環境で動作確認しています。

- macOS Mojave 10.14.3
- git version 2.20.1
- openjdk 11.0.2 2019-01-15
- Homebrew 2.0.1
- Docker version 18.09.1, build 4c52b90
- mysql Ver 14.14 Distrib 5.7.23
- Spring Tool Suite Version: 4.1.1.RELEASE

TerminalでそれぞれVersion確認をしてみて、コマンド自体が見つからない場合はインストールをしてください。

```
# macos
sw_vers

# git
git --version

# openjdk
java --version

# homebrew
brew --version

# docker
docker --version

# mysql
mysql --version

# Spring Tool Suite
# GUIアプリです。 インストールした記憶がない場合は https://spring.io/tools からDLしてインストールしてください。
```

----

## さっそく渡されてみましょう



```
# 作業フォルダを作成して移動します
mkdir -p ~/Documents/sample_sts_crud/
cd ~/Documents/sample_sts_crud

# STSプロジェクトを入手します
git clone https://gitlab.com/msrx9/sample_springboot_crud.git

#　MySQL環境を入手します
git clone https://gitlab.com/msrx9/sample_docker_mysql.git
```
これで必要なものは揃いました。CRUDデモアプリを起動させてみましょう。

### 1. MySQLサーバを起動します

docker-composeコマンドを使ってMySQLサーバを起動します。

```
cd ~/Documents/sample_sts_crud/sample_docker_mysql
docker-compose up
```

MySQLサーバを停止するときは、`CTRL + C` を打ち込んでください。


### 2. STSプロジェクトをインポートして実行

<img width="451" alt="sts_1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/27090/b8c0a462-7dd0-0ad6-3b3c-7f09db23adb0.jpeg">

File > Import を選択。

<img width="500" alt="sts_2.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/27090/e1e5d201-4d1a-0f50-4c3b-7aa54c56cb3d.jpeg">


Maven > Existing Maven Projects を選択。

<img width="500" alt="sts_3.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/27090/b2c0ffef-d55b-b19b-fe06-0c3d872a995f.jpeg">


Root Directoryに先ほど git clone したパスを選択。
私の場合ですと　`/Users/msrx9/Documents/sample_sts_crud/sample_springboot_crud
` になります。

<img width="766" alt="sts_4.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/27090/6d5c6e32-3da2-dd87-280e-c4ea34840c7e.jpeg">


プロジェクトを右クリックして Run As > 9 Spring Boot App を選択。
アプリが起動します。


### ブラウザでみてみましょう。

ブラウザで http://localhost:8080 にアクセスしてみましょう。

<img width="1231" alt="sts_5.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/27090/1b25ff19-7b5f-139f-534c-52903d51b365.jpeg">

こんな感じの画面が表示できたら無事に移植完了です。



----

## やってみてよかったなと思った点

- STSプロジェクトのapplication.ymlの内容とDockerで起動させるMySQLが確実に対応が取れるので、よく陥りがちなDBコネクトエラーが起きない。

- 全部Gitにコミットしてるので、渡された人もバージョン管理の恩恵を受けることが可能。初学者にありがちな「どこを変更したかわかりません」が減らせれるはず。

## やってみて残った疑問

- dockerの起動の部分をSTS側から制御できないものだろうか。CUIに慣れていない人に都度Terminalでコマンドを打たせるのも間違いの元になるため。

- jdkやmysql-client等もDockerで仮想化してみたかったがよくやり方がわからなかった。
  - vagrantでひとまとめにするしかない？
  - STSの起動にも必要だし、流石にjdkとかはローカルにインストールした方がよい？

- macOSならこの手順でいけるけど、Windowsの場合はVirutalBoxとDockerが競合するので、Vagrant+Dockerの形に手順を作り直すしかない？ せめて、再起動なしでHyper-VのON/OFFを切り替えられたらなぁ。
vwをremで直観的に数値化する簡単な方法

結論を先に書くと、以下でremを使用しvwを感覚的に扱えるようになります。

```
   html{font-size: calc( 1000vw / カンプサイズ );}
```
#remをvwに直結させる
750pxのデザインカンプを渡された場合で説明します。
2倍のレティ-ナ想定で、375pxの画面でコーディングします。この時、カンプの半分の大きさで、ぴったりになるように、サイズを調整すると思います。

レスポンシブの場合、単位は、remかvwかvminが多いと思います。ここで数値をカンプのママからはとらずに、換算もしくは、sassなど自動計算していたと思います。それが、計算不要となります。**カンプサイズが375px**を想定していた場合の例です。

    html{font-size: calc( 1000vw / 375 );}

カンプサイズが375pxの（100vw）ものを作成するときに、100vwを同じ大きさの375で割ると答えは1です。1pxが1remになります。10倍の1000vwだと、10pxが1remになります。

**カンプサイズが320px**を想定していた場合の例では


    html{font-size: calc( 1000vw / 320 );}

カンプサイズが320pxの（100vw）ものを作成するときに、100vwを同じ大きさの320で割ると答えは1です。1pxが1remになります。しかし、chromeでは10pxが文字の最小サイズとなっているため、1pxをfont-sizeとはできません。そこで10倍の1000vwをルートサイズをfontサイズとすると、10px=1remになります。

1rem=10pxにするために、62.5%としていたことを、vwと関係から、1000vwをデザインカンプの基準となる大きさで割ることで1remがカンプでの10pxになることを狙っています。

「html{font-size: calc( 1000vw / カンプサイズ );}」を入れることで、デザインカンプの実現にrem単位を使うことで、スマホ各種サイズに応じた拡縮を行えます。

```html:
<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    html{
      font-size: calc( 1000vw / 375 );/*カンプでの1rem=10px相当 お好みで*/
    }
  </style>
</head>
<body>
<p style="width:50vw;background: #fee">50vw</p>
<p style="width:18.75rem;background: #eef">18.75rem（375÷2）</p>
<p style="width:100vw;background: #fee">100vw</p>
<p style="width:37.5rem;background: #eef">37.5rem</p>
</body>
</html>
```

このやり方は、vwを元にrem換算しているので、デザインカンプから直感的に数値を挿入することができます。
sassでごにょごにょしたり、換算表やツールが不要になります。

画面サイズがカンプより小さければ、小さい比率に合わせてremの基準が変化します。font-size以外にも、あらゆるサイズに使えば、楽に閲覧者の画面サイズに対応することが可能となります。
可変して欲しくないサイズは、pxで記述しましょう。
#想定外に大きくさせない
大きい画面ではそれ以上に大きくなってほしくない場合があります。
そんな時のスポンシブ対応は、デザインカンプ以下のスクリーンサイズでいい場合には、メディアクエリを使いましょう。
【例：375pxのカンプ以下のみ割合に応じて縮小に】

```
html{
      font-size: 62.5%;
    }
@media screen and(max-width:375px) {
  html {
    font-size: calc( 1000vw / 375 );
  }
}
```

で対応。そうすることで、375pxの画面以上の場合には、カンプと同じ大きさで。画面サイズ320pxで見られた時には、100vw=320pxとなり、320/375=85.333…%で縮小表示されることになります。

これは、単位を必要とするすべての値にremを使用することで、画像を拡縮するかのようにすべての要素が拡縮されるようになります。
ユーザーが使用していないサブサイトをPowerShellを使って調べる

# 最終更新日にあたるプロパティが2つある

SharePoint Online サイトには最終更新日にあたるプロパティが2つあります。
・ LastItemModifiedDate
・ LastItemUserModifiedDate

この2つの違いを明確に説明した情報は見つけられていないです。
実際に値を取得して比較したところ、**おそらく**以下の違いがあると考えられます。

| プロパティ | 説明 |
|:--|:--|
| LastItemModifiedDate  | SharePointの定期ジョブなどシステムによる更新も含んだ最終更新日  |
|LastItemUserModifiedDate　　　　　　　　　  | ユーザー操作による最終更新日  |

# PowerShellを使って両方のプロパティを取得してみた

サブサイトを複数持つサイトコレクションで、PowerShell を使って「LastItemModifiedDate」と「LastItemUserModifiedDate」を取得してみました。

実行したコマンド

```powershell
Get-PnPSubWebs -Includes LastItemModifiedDate,LastItemUserModifiedDate | Select Title,LastItemModifiedDate,LastItemUserModifiedDate | sort LastItemUserModifiedDate -Descending
```

結果
（この情報は 2018/7/13 に取得したものです）
（サイト名は伏せています）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/357828/34aa850b-91f0-11d1-3d83-456640bd9403.png)

# 結論

「LastItemModifiedDate」はSharePoint内部で実行されている日毎・週毎の定期ジョブによる最終更新も取得している様子。なので、いつ取得しても 数日前 ～ 1週間前 くらいの日付が返される。（使いどころないかも）

「LastItemUserModifiedDate」はシステムによる更新は除外した最終更新日を取得している様子。なので、ユーザーに使われていないサブサイトの洗い出しに活用できそう。
C++ メモ

#はじめに
C++入門中です。
C++で配列を渡す際は、ポインタじゃないと行けないと
のことなので、試していたらVisual Studio 2017 Community にてできた内容です。
他の方が記事にしているかもしれません。
また、他のコンパイラでは確認していませんので、ご了承ください。
C++に詳しい方教えてください。

また、書いたこと忘れないために、
メモ程度です。

#C++ 関数のパラメータに配列を
下記プログラムは、エラーを出します。

```c++
#include <iostream>
void ar(const float a[4])
{
	std::cout << "a[0] = " << a[0] << "\n";
	std::cout << "a[1] = " << a[1] << "\n";
	std::cout << "a[2] = " << a[2] << "\n";
	std::cout << "a[3] = " << a[3] << "\n";
}
int main()
{
	ar({1.0f,2.0f,3.0f,4.0f });
} 
```

しかし、丸括弧で囲んだ参照渡しをすることで、
配列を指定することができました。

```c++
#include <iostream>

void ar(const float (&a)[4] = {1.0,1.0f,1.0f,1.0f})
{
	std::cout << "a[0] = " << a[0] << "\n";
	std::cout << "a[1] = " << a[1] << "\n";
	std::cout << "a[2] = " << a[2] << "\n";
	std::cout << "a[3] = " << a[3] << "\n";
}

int main()
{
	ar({1.0f,2.0f,3.0f,4.0f });
}
```

以上
Spring SecurityでCSRF対策を有効にしてログアウトを実装する時の注意点

###概要
本記事では、Spring SecurityでCSRF対策を有効にしてログアウトを実装した時に陥りがちなエラーとその対策について紹介します。

###動作確認環境
- OS: macOS Mojave 10.14.2
- Spring Boot version: 2.1.2.RELEASE

###Spring SecurityでCSRF対策を行なってログアウトを実装した時に陥りがちなエラー

Spring SecurityでCSRF対策を有効にしている状態では、データをPOSTで送信する時にCSRFのトークン値を送らなければなりません。Thymeleafを使用すると、formタグでth:actionを使用するだけで、CSRFのトークン値を自動作成し、送信します。
　したがって、Spring SecurityとThymeleafを使用した場合、CSRF対策には基本的にはformタグでth:actionを書くだけでいいのですが、リンクを使ってログアウトを実装する際には注意が必要です。
何も考えずにログアウトをGETで行うと404エラーが発生してしまいます。
　Spring Securityでは、基本的にはGETで送信する時にはCSRFのトークンチェックを行いませんが、ログアウトの場合にはGETで送信した時にもCSRFのトークンチェックを行います。しかし、GETで送信した場合にはトークン値は自動作成されません。
　したがって、ログアウトをGETで行なった場合、404エラーが発生してしまいます。以下に例を示します。

　以下のコードでログアウトを実装します。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>メインページ</title>
</head>
<body>
メインページです。
<a href="/logout">ログアウト</a>
</body>
</html>

```

　Spring Securityでは、ログアウトのリンク先に"/logout"を指定するだけでログアウトできるのですが、この状態でログアウトのリンクをクリックすると、404エラーが発生してしまいます。
![スクリーンショット 2019-02-11 15.55.37.png](https://qiita-image-store.s3.amazonaws.com/0/274610/e8f51d4b-9510-e94d-915e-164dd6c68e71.png)

###CSRF対策を行なった時のログアウト実装
ログアウトをGETで行なった場合、CSRFトークン値が自動作成されず、エラーになってしまうため、javascriptを使って以下のようにログアウト時のメソッドをPOSTに変更します。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>メインページ</title>
</head>
<body>
メインページです。
<form th:action="@{/logout}" name="logout" method="POST">
    <a href="javascript:logout.submit()">ログアウト</a>
</form>
</body>
</html>
```

すると、CSRF対策を有効にした状態でリンクからログアウトできるようになります。
[Unity] InspectorにDictionaryっぽい雰囲気のListを表示させてみた

実用性があるかは不明。

```ruby:SoundLib.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SoundLib : MonoBehaviour {

    public enum Bgms {
        bubble,
        bgm_test1,
        bgm_test2,
        bgm_test3
    }

    public enum Ses
    {
        btn_001,
        se_test1,
        se_test2,
        se_test3
    }

    [Serializable]
    private class AudioClips
    {
        [HideInInspector]
        public string id;
        public AudioClip file;
    }

    [SerializeField]
    private List<AudioClips> bgmList = new List<AudioClips>(Enum.GetNames(typeof(Bgms)).Select( s => new AudioClips() { id = s }));

    [SerializeField]
    private List<AudioClips> seList = new List<AudioClips>(Enum.GetNames(typeof(Ses)).Select( s => new AudioClips() { id = s }));

}
```

　Serializableなクラスの最初のフィールド変数がstringである場合、Inspector上のListの要素名は「Element 0」といった表記ではなく、stringの文字列に変更される。stringの変数自体は表示されていると見た目的に邪魔になるため、[HideInInspector]で非表示にした。
　上では実装していないが、enumをkeyとするDictionaryのようにアクセスできるようにしたい。

![Inspector.png](https://qiita-image-store.s3.amazonaws.com/0/359556/38d34ccc-a15f-6bda-e19f-00c1ae5af32c.png)
英語キーボードでの日本語入力切替をaltでトグル切り替えする方法

https://github.com/karakaram/alt-ime-ahk/releases にて、macライクに左側のaltで英語、右側のaltで日本語切り替えできます。しかしmacでトグル設定にしていて同じように使いたい人がいると思います。以下のように変更すると右側のaltにてトグル制御で英語と日本語を切り替えられます。

####手順1. https://github.com/karakaram/alt-ime-ahk/releases からソースコードを落としてくる

####手順2. alt-ime-ahk.ahk の"LAlt"を消して以下のように変更する

```c:alt-ime-ahk.ahk

*~RAlt::Send {Blind}{vk07}

; 右 Alt 空打ちで IME を ON
RAlt up::
	if (A_PriorHotkey == "*~RAlt")
	{
		if (IME_GET() == 0)
		{
			IME_SET(1)
		}
		else
		{
			IME_SET(0)
		}
	}
	Return
```

####手順3. AutoHotKeyをインストールしてalt-ime-ahk.ahkを右クリックからコンパイルを選択しexeを作成

####手順4. 作成されたexeを実行。（終了はTask Managerから）

#####参考資料：
https://www.karakaram.com/alt-ime-on-off

改変・再配布自由とのこと。
password cli [gopass]

最近使ってるpassword managerの紹介。keepass cliで良いのが見当たらないので、gopassが良いと思う。

https://github.com/gopasspw/gopass

gopassはgpgを使って自動認証。gitからdbを読み取っても使えるぽい。この場合、public-keyとfileをrepoに追加。

今回は、localで使用する方法。

```sh:install
$ brew install gopass
or
$ pacman -S gopass
```

```sh
# setup
$ gopass init
使用するpublic-keyを選択, 対応するsecret-keyがあれば認証可
$ gopass config 

# add password
$ gopass insert github/syui
$ gopass
github/syui
$ gopass github/syui
*********
```

```sh
# zsh
$ gopass completion zsh > ~/.zsh/functions/_gopass.zsh
$ . ~/.zshrc
```
youtube cli [mpsyt]


最近使ってるyoutube clientの紹介 [mpsyt]

[https://github.com/mps-youtube/mps-youtube](https://github.com/mps-youtube/mps-youtube)

![スクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/4151/f7dc9a5e-18da-7b2d-86e2-7610b2f22166.png)


```sh:install
$ pacman -S mps-youtube
or
$ brew install mps-youtube
```

```sh
$ mpsyt
> search synthv
> all
```
業務系テーブルをRailsに置き換えて考えてみる


昔、「業務系システムもRailsで良いんじゃね？」とか考えていて、作りたかったのですが、RailsやRuby自体のレベルが低すぎて挫折してしまいました・・・
Web系に転職した今なら、挫折した経験を乗り越えられるんじゃないかと思い、今回、Railsで業務系システムのテーブルの関係性について考えてみました。

### belongs_to (一方向の参照)
例:　製品受注管理
受注した製品を保管するテーブル__received_orders__があるとします。
この__received_orders__から製品マスタである__products__テーブルを参照し、製品の情報を付与した状態で受注を管理したいという場合、__belongs_to__を使います。

__received_orders__のproduct_idから__products__のidを検索して、製品の情報を取得する事が出来ます。

![スクリーンショット 2019-02-12 2.30.56.png](https://qiita-image-store.s3.amazonaws.com/0/343136/3137e522-9acb-a741-dee9-23b73018f31a.png)

### has_many (1対多の関係)

先程の__belongs_to__の例を逆から見てみましょう。
__received_orders__は同じ製品を何回も受注する可能性があるため、同じ製品を何件も入力する事が出来ます。
一方、製品マスタである__products__は、同じ製品が入る事はありません。複数あったらどれが本当の製品情報なのか分かりませんね。
このような１つの__products__オブジェクトに対し、複数の__received_orders__が存在する事状態を__has_many__を使って表す事が出来ます。

![スクリーンショット 2019-02-12 2.49.34.png](https://qiita-image-store.s3.amazonaws.com/0/343136/bc511e38-6aa6-bfbf-2437-eca09166be9f.png)

### has_one

例: 製品マスタと対の価格マスタ　(1対1の関係)
製品マスタに価格情報を加えたいけど、価格情報って価格、仕入れ値、掛け率、消費税、etcと管理する種類多すぎ！
価格マスタという専用のマスタを作成した方が良いといった場合を想定します。
製品マスタと対にした価格マスタ__price__をつくり、製品マスタ__products__のAという製品の価格情報は、価格マスタ__prices__のAという価格を参照するといった1対1の関係は、__has_one__を使い表します。

![スクリーンショット 2019-02-12 3.20.30.png](https://qiita-image-store.s3.amazonaws.com/0/343136/6b9f1f9b-4ce8-b857-1371-626e59de86d2.png)

### has_many through (多対多)

例: 発注管理
受注した製品の在庫がない場合、在庫発注する業務があり、発注を管理する__management_orders__と実際に発注したデータを入れる__orders__があります。
実際の運用では人が考えて管理する部分になり、多対多の複雑なものに対応しなければなりません。
例えば、__received_orders__にAという製品１000個×2の注文が来たとして、発注する業者が、「この時期、工場のキャパシティが限界で、一気に2000個も納品出来ません。500×4の発注にして下さい。」と言われるとか、色々なパターンがあり得ると思います。__has_many through__を使い、多対多で管理しましょう。

![スクリーンショット 2019-02-12 3.25.03.png](https://qiita-image-store.s3.amazonaws.com/0/343136/15df30fd-fff1-6a81-aa5b-e9faeefb0675.png)



こうやって考えていくと複雑なリレーショナルデータベースにも対応出来そう！
挫折した過去を乗り越えられそうで、モチベーションアップです！！
FileManager.default.createFile

createFile(atPath:,  contents:, attributes:)のatPathパラメータはfile://スキーマで修飾されていない
パスをとる。
他のメソッドにpathストリングを渡すときのようにurl.absoluteStringをするとエラーになる。

let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let path = url.appendingPathComponent("foo.txt").path
FileManager.default.createFile(atPath: path, contents: nil, attributes: nil)
unityの教科書　レベル3~7 メモ

#ToStringで使う書式指定子
整数型 : D[桁数] 
例)
(456).ToString("D5"); → 00456
固定小数点型 : F[桁数]
例)
(12.3456).ToString("F3"): → 12.345

#GameObjectとgameObjectの違い
GameObject : 変数
gameobject : そのスクリプトがアタッチされたオブジェクト
 
# Instantiateについて
Instantiateメソッドは最も基本的な「Object型」を返すため別の型(例えば「GameObject型」が受け取りたいときはキャストと呼ばれる強制型変換を使う
例)GameObject (変数名） = Instantiate(○○Prefab) as GameObject;

#プレイヤの向き変更のやり方
TransformコンポーネントのlocalScale変数を使う
例)transform.localScale = new Vector3(a,b,c)
a : -1〜1で向きを示す
b : X軸方向への拡大率
c : Y軸方向への拡大率

#Physicsを使うときの注意点
オブジェクトを動かすときは座標を操作するのではなく「力」をかける

#isKinematicを使う意味
動いているオブジェクトをある地点で止めたいときとか
例）GetComponent<Rigidbody>.isKinematic = true;

#ワールド座標系とスクリーン座標系の変換
ScreenPointToRayというメソッドを使う
このメソッドはスクリーン座標を渡すとカメラからスクリーン座標に向かうワールド座標系でのベクトルを渡してくれる
例)Ray ("変数名") = Camera.main.ScreenPointToRay(Input.mousePosition);

※Rayは光源の座標と光源の方向をメンバ変数に持つ
[備忘録]radikoタイムフリーを録音しクラウドへアップロード

##経緯
タイムフリーであっても聞き忘れがよくあるどうにかならないか…
↓
偉大な方々がradikoを録音するスクリプトを公開している！！！
↓
用途未定のRaspberry Pi 3B+発見
↓
スクリプトを加えて自動でRaspberry Pi本体に録音させる！！
↓
外でも聞きたい
↓
Google Driveにアップロードして外出先で楽しむ

##今回使用するもの
curl
Xmllint
FFmpeg
rec_radiko_ts
cron
gdrive
##カレントディレクトリの確認
```
pi@raspberry:~ $ pwd
```
の実行結果が /home/pi であることを前提に記載します。

##FFmpegのインストール
```
pi@raspberry:~ $ sudo apt-get install ffmpeg
```

##Xmllintのインストール
```
pi@raspberry:~ $ sudo apt-get install libxml2-utils
```
##レポジトリ「rec_radiko_ts」をクローン
```
pi@raspberry:~ $ git clone https://github.com/uru2/rec_radiko_ts
```
##好きな番組を録音するスクリプトを書く！
サンプルは全国で聴取可能な「ラジオNIKKEI第２」の
「RN2 8 朝は音楽のシャワーから」です。

```MorningMusicShower.sh
#RN2はラジオNIKKEI第２ ※この部分は放送局により異なる
u="http://radiko.jp/#!/ts/RN2/"
#rは番組放送日時後で自動実行するので変数表記
r=`date +%Y%m%d`
#lは番組開始時間表記は"HHmmss"
l="080000"
#Dは保存先ディレクトリ
D="/home/pi/Radiko/"
#Bはファイル名に付与する放送局名
B="[ラジオNIKKEI第２]"
#Tはファイル名に付与する番組名
T="_朝は音楽のシャワーから.m4a"
#PATH通せば書き方変えれるけど面倒…
sh /home/pi/rec_radiko_ts/rec_radiko_ts.sh -u $u$r$l -o $D$B$r$T
```
保存先を /home/pi/MorningMusicShower.sh にしておく
（パスを通す作業工程を省略するため）

##gdriveの初期設定
griveの設定は「サーバのバックアップファイルを Google ドライブに退避させる」を引用しています。

```
pi@raspberry:~ $ wget -O drive https://docs.google.com/uc?id=0B3X9GlR6EmbnVXNLanp4ZFRRbzg
pi@raspberry:~ $ sudo mv drive /usr/sbin/drive  
pi@raspberry:~ $ chmod 755 /usr/sbin/drive
```
drive コマンド初回実行時に認証用の URL が出力され、認証キーの入力が求められる。
別途ブラウザから出力された URL にアクセスして認証コード取得してコピペしてあげればいい。
※下記の認証用 URL はダミー

```
pi@raspberry:~ $ drive about
Go to the following link in your browser:  
https://accounts.google.com/o/oauth2/auth?client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&state=state
Enter verification code: (認証コード入力)
```
##Google Driveへアップロードを追記する
```MorningMusicShower.sh
#RN2はラジオNIKKEI第２ ※この部分は放送局により異なる
u="http://radiko.jp/#!/ts/RN2/"
#rは番組放送日時後で自動実行するので変数表記
r=`date +%Y%m%d`
#lは番組開始時間表記は"HHmmss"
l="080000"
#Dは保存先ディレクトリ
D="/home/pi/Radiko/"
#Bはファイル名に付与する放送局名
B="[ラジオNIKKEI第２]"
#Tはファイル名に付与する番組名
T="_朝は音楽のシャワーから.m4a"
#PATH通せば書き方変えれるけど面倒…
sh /home/pi/rec_radiko_ts/rec_radiko_ts.sh -u $u$r$l -o $D$B$r$T
/usr/sbin/drive upload $D$B$r$T
#アップロード先のフォルダ指定は
#drive --parent "Folder ID" $D$B$r$T
#"Folder ID"はdrive listで確認
#アップロードしたらファイルを削除
#アップロードに失敗することが意外と沢山ある…ので消さない…
#rm -r $D$B$r$T

```
##定期実行「cron」の設定
```
#以下コマンドのpiはユーザー名
pi@raspberry:~ $ crontab -u pi -e
出てきたEditで追記する！

#番組終了後30分後に動作開始タイムフリーの制約？で
#分 時 日 月 曜日 コマンド
30 09 * * 1-5 sh /home/pi/MorningMusicShower.sh
```
曜日は0と7が日曜日で1が月曜日…なので1-5は平日(月~金)の9時30分にMorningMusicShower.shを実行する！的な感じです。

##謝辞・参考・引用
https://github.com/uru2/rec_radiko_ts/
https://qiita.com/aviscaerulea/items/53123ce5b79c80e31a71
https://github.com/prasmussen/gdrive
【Python】シーザー暗号

# 概要
暗号理論の入門として、シーザー暗号をPythonで実装します。
平文の全ての文字を特定文字数ずつシフトすることで、暗号文を作成します。
復号の際は、逆方向にシフトすることで平文を作成する。

# 実装

# 暗号化
例として、３文字文シフトして暗号文を作成する。

```python
# 平文
PLAIN = "apple"

# 秘密鍵
KEY = 3

# 以下に、記述してください。
enc = ""

for char in list(PLAIN):
    ASCII = ord(char)
    num = ASCII - 97
    num = (num + KEY) % 26
    ASCII = num + 97
    enc += chr(ASCII)

print(enc)
```

```none:出力結果
dssoh
```

[![alt](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuG8pkAoUpPh-j7_xisdjjkhgrbn5gGMfYILS2a1WPGWKVBeMA3ljSLFNq_PTZnjdMaDa78ETFJqLalDJKXythdwwfFDP_soeZ97PuwP9ppPFVTou0gZySLFtipcTBsTEUB9tykF6vJ5vJtTk1XeAb7o-VCRJzMqlUxS2bJ_jMl1ytNGiHdS_Rkg4k05epSk6DcIR4Ev6bdlS25Gw7w87QFAB_Nk1XiDyfL2UaPcJofMQbyBb02I0OG00)](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuG8pkAoUpPh-j7_xisdjjkhgrbn5gGMfYILS2a1WPGWKVBeMA3ljSLFNq_PTZnjdMaDa78ETFJqLalDJKXythdwwfFDP_soeZ97PuwP9ppPFVTou0gZySLFtipcTBsTEUB9tykF6vJ5vJtTk1XeAb7o-VCRJzMqlUxS2bJ_jMl1ytNGiHdS_Rkg4k05epSk6DcIR4Ev6bdlS25Gw7w87QFAB_Nk1XiDyfL2UaPcJofMQbyBb02I0OG00)

## 復号

３文字文逆方向にシフトして、平文を作成する。
２６を法とする有限体で平文と秘密鍵を減算すれば復元できる。

```py
# 暗号文
ENC = "dssoh"

# 秘密鍵
KEY = 3

# 以下に、記述してください。
plain = ""

for char in list(ENC):
    ASCII = ord(char)
    num = ASCII - 97
    num = (num - KEY) % 26
    ASCII = num + 97
    plain += chr(ASCII)

print(plain)
```

```none:出力結果
apple
```

[![alt](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuG8pkAoUxjpyR5gxhRgwDLTHQa5gOWcN0X1O6G85dwwT_hH_skEchgVjknutphI6o3W6EtjwAYJdfwG-RbpzT4ddi_xPK1aZiyTDavvjdlguSGLG-UEcxcTpEb_EdF1ax-J7ZSjZyY0s0IMVBv_nT7tRozwj8EKxPZzVDnsBqTsFcpeXRW1QyxAX3SMcPxE0BjiEb4QMUzm8L3eVeWTeyelzUvzsBO3vIg4y8pCdbIirBuNB0KW00m00)](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuG8pkAoUxjpyR5gxhRgwDLTHQa5gOWcN0X1O6G85dwwT_hH_skEchgVjknutphI6o3W6EtjwAYJdfwG-RbpzT4ddi_xPK1aZiyTDavvjdlguSGLG-UEcxcTpEb_EdF1ax-J7ZSjZyY0s0IMVBv_nT7tRozwj8EKxPZzVDnsBqTsFcpeXRW1QyxAX3SMcPxE0BjiEb4QMUzm8L3eVeWTeyelzUvzsBO3vIg4y8pCdbIirBuNB0KW00m00)

# ブルートフォース攻撃
シーザー暗号で暗号された文字列に対して、ブルートフォース攻撃をしてみる。
アルファベット27通り全てに対し、復号アルゴリズムを実行する。

```py
# 暗号文
ENC = "dssoh"

# 以下の復号アルゴリズムを用いて、
# 秘密鍵の値を26通り全て出力してみよう！
for KEY in range(26):
    plain = ""

    for char in list(ENC):
        ASCII = ord(char)
        num = ASCII - 97
        num = (num - KEY) % 26
        ASCII = num + 97
        plain += chr(ASCII)

    print(plain)
```

```none:出力結果
dssoh
crrng
bqqmf
apple
zookd
ynnjc
xmmib
wllha
vkkgz
ujjfy
tiiex
shhdw
rggcv
qffbu
peeat
oddzs
nccyr
mbbxq
laawp
kzzvo
jyyun
ixxtm
hwwsl
gvvrk
fuuqj
ettpi
```

出力結果より、平文は`apple`であると推測できる。

# まとめ
シーザー暗号に対する、暗号化・復号・ブルートフォース攻撃を実装しました。
暗号アルゴリズムを実装してみることで、理解が深まると思います。
間違い・指摘等があればコメントお願いします。