OmniAICreator/Qiita-1.07M huggingface dataset:
Core Imageによるぼかしのクオリティを高める

Core Imageを使うと、簡単かつ高速に画像ぼかすことができます。

<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/b7031335-7a0e-5e7b-1790-b7fd1e718f97.gif">
(↑はgif化しているので見た目がいまひとつですが...)

ぼかし自体は `CIGaussianBlur` ひとつでできるのですが、以下の点に注意しておくことでより高いクオリティの結果を得ることができます。

* ぼかし後の画像サイズは、入力画像サイズと異なる
* なにもしないと、画像のエッジ付近がやや暗くなってしまう

## `CIImage#extent` について

`CIImage#extent` は簡単に言うと、その画像のサイズを持つ出力矩形領域です。
例えば解像度480x640の画像から作られた `CIImage` の `extent` は `(x: 0, y: 0, w: 480, h: 640)` となります。
しかしこれに、半径 `20` の `CIGaussianBlur` を適用すると、 `CIImage#extent` は `(x: -60, y: -60, w: 600, h: 760)` となり、入力画像よりも大きな画像が出力されていることがわかります。
これをImage ViewなどにAspect Fit表示すると、元画像より相対的に小さく表示されてしまうでしょう。

<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/0ba3758d-dc1f-304f-7465-54bda60d5283.png">

入力画像と同じ大きさで表示したければ、 `CIImage#cropped(to:)` などで入力画像の `extent` で切り取る必要があります。

## ぼかし画像のエッジ付近が暗くなってしまう理由

ぼかしフィルタは一般的に、対象ピクセルを中心とした半径r内にあるピクセルの値(色)の加重平均を求めて生成します。
しかし画像のエッジ付近については、サンプリングする範囲が画像の外に及んでしまうため、その部分の値を「黒」とみなして計算した結果、暗い色になってしまうことがあります。

この問題の対処方法のひとつとして [CIAffineClamp](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIAffineClamp) を利用する方法があります。
↑のリファレレンスにもどんな結果が得られるか記載されていますが、 **画像の外のピクセル値を、最寄りの四辺のピクセル値と同じとみなすようCore Imageに指示することができる** のです。

## CropとClampedToExtentを適用したぼかしフィルタ

以上を踏まえたCore Imageによるぼかしフィルタは以下のようになります。

```CoreImage_BetterBlur.swift
// inputImage: CIImage, radius: CGFloat
let outputImage = inputImage
    .clampedToExtent()    // CIAffineClamp
    .applyingFilter(
        "CIGaussianBlur",
        parameters: [kCIInputRadiusKey: radius]
    )
    .cropped(to: inputImage.extent)
```

* 左: clampedToExtentあり
* 右: clampedToExtentなし

<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/dd51661b-dd9d-363e-3455-994833c093b7.png">　<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/8a138e6a-9417-2d61-892b-fb4733bb04bd.png">
個人向けLinux版アンチウイルスソフトの簡単まとめ

## え、EOL？

filunKは普段使いでLinuxノートPCを使用しているのですが。
この度、__愛用のアンチウイルスソフト Sophos Antivirus for Linux(SAV for Linux)が製品サポート終了__とのことです。
特にアナウンスらしいアナウンスはないですが、ダウンロードページが削除されている上、サポートに問い合わせたところ、

> 製品サポート終了のため、リンクを削除しました

とのこと。

[Sophos](https://www.sophos.com/)

ということで、移行先を見つけなければならないのですが。
なにしろ、Linux向けセキュリティソフト。法人向けではたくさん選択肢があるのですが（Sophos製品も、法人向けのSophos Centralの一部として、SAV for Linuxは継続らしいです）、個人向け製品となると中々情報が見つからず。

なので、簡単にまとめてみました。

## 無償製品

各アンチウイルスソフトの無償版・OSSが当てはまります。以前はLinux向けアンチウイルスは無償で色んな所から出ていた記憶なのですが、今はほとんどが法人向けにシフトしたり、そもそもEOLになってしまったりと残念。探した限りだと、無償版に当たる製品は見つけられず。
__情報があったらコメントください__

### ClamAV

[ClamAV](https://www.clamav.net/)

みなさんご存知（?）、OSSのアンチウイルスソフトです。昔からLinux向けアンチウイルスソフトとしては必ず名前が上がります。各ディストリビューションのパッケージに含まれているので導入は簡単でしょう。

ただ、filunKが移行先にしなかったのは

1. スキャン時に端末が重くなりがち
2. オンアクセススキャンにたいして明示的な設定が必要 & 指定先ディレクトリ以下を再帰的にオンアクセススキャンしてくれない

という印象があったためで。
アンチウイルスをなるべくソフトに丸投げしたいfilunKとしては煩わしいし操作の邪魔をしかねないので見送りました。

### Linux Malware Detect

[Linux Malware Detect(aka LMD, maldet)](https://www.rfxn.com/projects/linux-malware-detect/)

更にOSSのアンチウイルスとして、このようなものがあるみたいです。アンチウイルス機能を持っていますが、ClamAVをエンジンとして使用できるようになっているらしく。
ほとんど情報が見つからず、移行対象としてピックアップできませんでした。
Qiitaだと以下のエントリが見つかるぐらい？

[マルウェア検出ツール Linux Malware Detec](https://qiita.com/bezeklik/items/43a7d4fce6bc23fe84d3)
[Linux Malware Detectを試してみた[CentOS7.6]](https://qiita.com/nozomu0321/items/f300fb62e2db42906aca)

## 有償製品

各企業が個人向け有償版として展開しているアンチウイルスソフトです。

### NOD32 Antivirus for Linux Desktop

[Legendary antivirus for Linux; ESET NOD32 ANTIVIRUS FOR LINUX DESKTOP](https://www.eset.com/us/home/antivirus-linux/)

$39.99/１年１台
スロバキア企業ESET社が展開するアンチウイルスソフトです。日本ではキヤノンITSが代理店として販売していますが、Windows版とMac版のみしか販売していません。~~な　ぜ　販　売　し　な　い~~
そのため、Linux版はESET社から直接購入する必要があります。購入のやり取りは当然英語、製品もおそらく日本語UIは存在しないかと。

### Dr.Web Antivirus for Linux

[Dr.Web Anti-virus for Linux](https://products.drweb.co.jp/home/linux/)

￥2900 + 税/１年１台
ロシア企業Doctor Web社が展開するアンチウイルスソフトです。日本語サイトの用意があり（ただしリンク先によっては__ロシア語__になる）日本円での決済も可能です。
Dr. Webは有名所のウイルステストAVtestなどに参加していませんが、

> 侵入時点においてテストされるアンチウイルスのデータベースには入っていない、未知なる脅威に対抗できるかどうか、こうした能力については全くテストされません。

という理由などから参加をやめたとのこと。詳しくは以下の記事を参照ください

[Doctor Web: statement on Virus Bulletin comparative reviews](https://news.drweb.com/show/?i=83&c=12&lng=en&p=0)

ロシア公官庁での導入実績もあるとのこと。何より日本語UIがあるので、今回はこちらに移行することにしました。

## 最後に

Linuxだからアンチウイルスはいらない、と考えている方は多いと思います。
確かに厳密な所有権ベースのアクセス制御、標準搭載のファイアウォールなど、マルウェア対策という点では優越性はあるかもしれませんが、クラウドなどでLinuxが多用されるようになっている昨今、Linuxが安全だとはfilunKには思えません。
Linuxをデスクトップ用途で利用している方がアンチウイルス導入を考えるきっかけになってくれれば、あるいは、同じ課題を抱えている方の参考になればと思います。
~~Sophos Centralが個人でも利用できるようになるか、Sophos HomeにLinux版が出ないかなー~~
Adobe AcrobatでのPDF容量を圧縮して署名情報を削除する方法


WebサイトでPDFをダウンロードファイルとして使用する場合の注意点として、
次の2つをチェックしましょう。

1. 容量を軽量化するようにする。
2. 文書作成時に自動で署名が入った場合は公開前に削除する。

それぞれAdobe Acrobatの対応方法をご紹介します。

## Adobe AcrobatでPDF容量を圧縮する方法

モバイルやWi-Fiのダウンロードを考えてPDFの容量を圧縮しておきましょう。
フルカラー図版が入ったファイルは容量が大きくなるので注意が必要です。

図版が入った6.4MBのサンプルファイルで実験しました。

![Alt text](https://i.gyazo.com/0a5601dec3d8b36b6903ec22820612cc.png)

# Adobe Acrobatでメタデータなどの非表示情報を削除する方法

PDF署名情報やコメントなど非表示情報を削除する方法です。

WordやPowerPointなどMicrosoft製品で署名を登録している場合、
PDFに会社名や個人名が表示される場合があります。
このような情報は削除しておきたいです。

## ツール＞墨消しを選択

メニュー：ツールをクリックし墨消しを選択します。

![Alt text](https://i.gyazo.com/abd0e29922f0d18035ef6106132d0c0a.png)

## 非表示情報をすべて削除をクリックする

画面が切り替わります、上部メニューの「非表示情報をすべて選択」をクリックします。

![Alt text](https://i.gyazo.com/b84bd7b5dae265c5ab29a08b96332145.png)

## 非表示情報を削除したファイルを保存する

ダイアログが出ますので保存します。

![Alt text](https://i.gyazo.com/2c80bbe435dfb63dbb402e0c2139d196.png)

以上となります。ご参考になれば幸いです。


# 参考URL

PDFを圧縮する方法 | Adobe Acrobat DC
https://acrobat.adobe.com/jp/ja/acrobat/how-to/compress-pdf.html
Adobe公式のPDF圧縮チュートリアルです。英語のビデオ教材もあります。

PDF 内の機密情報の削除- Adobe Acrobat DC
https://helpx.adobe.com/jp/acrobat/using/removing-sensitive-content-pdfs.html
Adobe公式の機密情報削除マニュアルです。
Node.jsのバージョンあげたら「Node Sass could not find a binding for your current environment」とでた場合

# 概要
Node.jsのメジャーバージョンをあげると、node-sassがエラーをはくことがある

**「Node Sass could not find a binding for your current environment」**

そのときは、node-sassをリビルドして自分のnode環境に合った状態にする

## 対処法

```
npm rebuild node-sass
```

これでOK

## そのほか対処法

それでもだめなら

```
npm rebuild node-sass --force
```

それでもだめなら、いったんnode-sass消してから。いれなおす。
（入れ直しでも、環境にあった適切なbinaryが生成される）

```
npm uninstall node-saas
npm install node-sass --save-dev
```
save save!の違い

##！の有無の違いは？
`create!`、`save!` →　レコードの作成・保存に失敗　→　例外を発生させる
`create`、`save` →　レコードの作成・保存に失敗 →　nilを返す

##なぜ、例外を発生させる？
RailsのTransactionにおいて、ロールバックが発火するには「例外」が必要であるから。
>例えば、Railsでは #update_attributeは例外を発火せずに、falseに返すとなる。そのため、#update_attributeを使うには、結果を見て、例外をスローする必要がある。Railsではびっくりマーク!がついているメソッドは、失敗したら例外をスローすると意図するので、transactionを使うときは、saveではなくsave!、destroyではなくdestroy!を使うべきでしょう。

参考記事
RailsのTransactionの使い方:https://qiita.com/huydx/items/d946970d130b7dabe7ec
Railsで感嘆符！を理解しよう（save, save!）:https://qiita.com/ozin/items/5968971c9d2b3ab0a84d
【初心者向け】API利用の基本テクニック(ローディングの描画と標準時間の変換について)

# 背景とこの記事の目的
この度、TwitterAPIを利用したWEBアプリを構築しました。
その際に、「あーこの技術は今後も間違いなく活用するだろうなー」と思ったものがいくつかあったので、備忘として残します。
便利なライブラリもあったのでそちら紹介も兼ねます。
※フロントはvueで作っていますので、その前提で以下のトピックを紹介していきます。

# 目次
1.非同期通信の際のローディングでぐるぐるさせるやつ（スピナー、インジケーター）
2.APIのレスポンスの中にある時刻を日本時間に変換する

## 非同期通信の際のローディングでぐるぐるさせるやつ（スピナー、インジケーター）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635205/3fdf297f-e4c7-80e6-5e7c-c0e07eda77a6.png)
こういうの実装したいと思ったことは皆さん誰しも一度はあるでしょう。
API通信で時間のかかる処理などでは非常に重宝します。

もし皆さんがvueを使っているのであれば、「vue-loading-overlay」をおすすめします。
詳しい使い方は以下が参考になります。
https://www.npmjs.com/package/vue-loading-overlay
https://www.kabanoki.net/4916/

カスタマイズもある程度できますし、比較的コードの記述量も少ないです。
axiosと組み合わせると以下のような書き方になります。

```js:App.vue
//scriptタグ内の記述
import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';

export default {
  name: 'app',
  data(){
    return {
      isLoading: false,
      fullPage: true,
    }
  },
  components:{
    "loading":Loading
  },
methods:{
      getTimeline:function(){
        alert('Timelineを取得します');

        //overlayの処理
        let self = this;
        self.isLoading = true;

        axios
          .get('APIのURL',
            {
              headers: {
                //必要に応じて記載
              },
              params:{
               //必要に応じて記載
              }
            })
          .then(response => {
            // handle success
            self.isLoading = false;
          })
          .catch(function (error) {
            // handle error
            self.isLoading = false;
            console.log(error);
          })
    },
    onCancel:function() {
      console.log('User cancelled the loader.')
    }
//以下略
```

```html:App.vue
<!-- templete内の記述 -->
<loading :active.sync="isLoading" :can-cancel="true" :on-cancel="onCancel" :is-full-page="fullPage"></loading>
<button v-on:click="getTimeline" class= "btn btn-primary"> Timelineを取得 </button>
```

## APIのレスポンスの中にある時刻を日本時間に変換する

TwitterのAPIのレスポンスの中に
"created_at": "Thu Apr 06 15:28:43 +0000 2017"
こういうものがありました。
APIのレスポンスには、必ずと言っていいほど時間に関する情報が入っています。そして日本のサービス出ない限り、大抵は標準時で入っています。
これを日本時間に変換する処理をする際は「Moment.js」というライブラリが便利です。

詳しい使い方は下記が参考になります。
https://qiita.com/osakanafish/items/5ef636bbcb2c3ef94953
https://momentjs.com/

実際の例としては以下の通り

```js:App.vue
const moment = require('moment');
require('moment-timezone');

//略(APIの処理)
.then(response => {
let obj = JSON.parse(response.data);
moment.tz.setDefault('Asia/Tokyo'); //日本時間に合わせる

for(var t=0; t<obj.length; t++){
   obj[t].created_at = moment(obj[t].created_at,'dd MMM DD HH:mm:ss ZZ YYYY','en').format('YYYY-MM-DD_HH:mm:ss');
}

```

日付の記法は地域（というか国？）によってほんとに様々あるようで、それに応じてコーディングも微妙に変える必要があるようですね。


# まとめ
実際に作ってみるといろいろと細かいテクニックが必要になることがよくわかりました。
ボタンの活性・非活性の制御、モーダルウィンドウ（子画面）の作り方、無限スクロールの実装の仕方などなど
上げればキリがないのですが、有用そうなものは時間があるときに記事にして残そうと思います
to_○　

##to_○
```ruby
x = 50
y = "3"

p x + y.to_i #to int
p x + y.to_f #to floo


scores = {keiichi:400, tomomi:2000}

p scores.to_a #to arry 
p scores.to_h #to hassh 
```

##%記法

```ruby

puts ("red", "blue")

puts %(hello) #でＯＫ　間に””を使用できる

p ["red", "blue"]

p %W(red, blue)　#でＯＫ

```
#if 
```ruby

score = gets.to_i


if score > 80 then
        puts "great!"
else if score > 60 then
    puts "good"

else
    puts "so so..."

end

```
##case
```ruby
#case

signal = gets.chomp #最後の改行コードを取り除くchomp

case signal
when "red" 
    puts "stop!"
when "green" 
    puts "go!"
when "yello" 
    puts "caution!"
    
else
    puts "wrong signal"

end

```
##While
```ruby
#while

i = 0

while i < 10 do
    
    puts "#{i}: hello" # #{i}は回数を見やすくする為に使用
    
    i += 1 #i = i + 1を短縮して書ける
    
end
```
##Times

```ruby
#times

10.times do |i| #i += 1と同じ効果
    puts "hello"
end
```
##for
```ruby

for i in 15..20 do
    p i
end

for color in ["red", "blue"] do
    p color
end

for name, score in {taguchi:200, fkoji:400} do
    puts "#{name}: #{score}"
end

for color in %W(red, bule) do
    p color
end
```
##each
```ruby

(15..20).each do |i|
    p i
end

["red", "blue"].each do |color|
    p color
end

{taguchi:200, fkoji:400}.each do |name, score|
    puts "#{name}: #{score}"
end

%W(red, bule).each do |color|
    p color
end
```
Effective Java privateのコンストラクタでインスタンス化不可能を強制する

Effective Javaの独自解釈です。
第3版の項目4について、自分なりにコード書いたりして解釈してみました。
# 結論
staticメンバしか持たないクラスには、実行時例外を出すprivateコンストラクタを用意しよう。
# 説明
例えば共通の処理だけを集めたユーティリティクラス（以下、Utilクラス）はstaticメソッド、static変数のみを持ち、インスタンス化を前提としていない。

一般にpublicなUtilクラスは、コンストラクタを定義しないとpublicなデフォルトコンストラクタが用意されるため、外部のクラスで無駄にインスタンス化されてしまう懸念が生じる。


明示的にprivateコンストラクタを定義することで、Utilクラス外でのコンストラクタ呼び出しを防ぐことができる。
また、コンストラクタに例外出力処理を入れることで、Utilクラス内でのコンストラクタ呼び出しをエラーとすることができる。

※Utilクラスそもそもいらない論はここでは無視。
# コンストラクタ定義なしコード（ダメな例）
**Utilクラス**

```java
public class SampleUtil {

    public static final String HOGE = "hoge";

    public static String fugaMethod() {
        return "fuga";
    }
}
```

**呼び出し側クラス**

```java
public class SampleService {

    public String sampleMethod() {
        // 無駄にインスタンス化
        SampleUtil sampleUtil = new SampleUtil();
        return sampleUtil.fugaMethod();
    }
}
```

呼び出し側クラスでインスタンスを作っています。`fugaMethod()`はstaticメソッドなので、インスタンス化するのは無駄です。

# privateコンストラクタ定義ありコード（良い例）
**Utilクラス**

```java
public class SampleUtil {

    // privateかつ実行時例外を出力するコンストラクタを定義
    private SampleUtil() {
        throw new IllegalStateException("Util instance construction is not allowed.");
    }

    public static final String HOGE = "hoge";

    public static String fugaMethod() {
        return "fuga";
    }

}
```

**呼び出し側クラス**

```java
public class SampleService {

    public String sampleMethod() {
        return SampleUtil.fugaMethod();
    }
}
```

コンストラクタがprivateなので、別のクラスではそもそもインスタンス化できません。

また、仮にUtilクラス内でコンストラクタが呼ばれたとしても、例外が出力されるためインスタンスが作られることはありません。コンストラクタを呼ぶようなコードが書かれている場合、それはプログラミングエラーなので、実行時例外を出すようにしましょう。

※コンパイルは通るので、プログラミングエラー自体を防ぐことはできません。
【Java】LocalDateTimeクラスで日付を取得する

#まずはimportが必要

```java
import java.time.LocalDateTime;
```
でパッケージの利用を宣言する必要があります。
**Eclipse**を使用している場合は宣言する前にLocalDateTimeのインスタンス化をすれば自動的にimport文が挿入されるようです。超便利ですね。

#現在の日付を取得してみよう

```java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; // 形式を指定する場合はこのパッケージ宣言が必要

public class Sample_01 {

	public static void main(String[] args) {
		LocalDateTime d = LocalDateTime.now(); // 現在時刻のインスタンスを取得
//		LocalDateTime d = LocalDateTime.of(2016,  1, 1, 10. 10, 10); // 特定の日付のインスタンスを取得
//		LocalDateTime d = LocalDateTime.parse("2016-02-02T10:10:10"); // isoが指定する書式で特定の日付のインスタンスを取得
//		
		System.out.println("d: " + d);
		System.out.println("getyear(): " + d.getYear()); // 西暦を取得
		System.out.println("getMonth(): " + d.getMonth()); // 西暦を取得
		System.out.println("getMonth().getValue(): " + d.getMonth().getValue()); // 西暦を取得
		System.out.println("plusMonths(2).minusDays(3): " + d.plusMonths(2).minusDays(3)); // 西暦を取得
		LocalDateTime nd = d.plusMonths(2).minusDays(3); // 日付の計算
		System.out.println("nd: " + nd); // 変数に入れて出力
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd/");
		System.out.println("DateTimeFormatter.ofPattaern: " + d.format(dtf));
	}

}

```

```:実行結果
d: 2020-09-12T14:42:11.438
getyear(): 2020
getMonth(): SEPTEMBER
getMonth().getValue(): 9
plusMonths(2).minusDays(3): 2020-11-09T14:42:11.438
nd: 2020-11-09T14:42:11.438
DateTimeFormatter.ofPattaern: 2020/09/12/
```
####ポイント
* println(d)だとISOの形式で日付が出力できる
* LocalDateTime nd = d.plusMonth(2)などで日付をずらしたものを別の変数に代入することも可能
* DateTimeFormatterを使う場合は`import java.time.format.DateTimeFormatter;`が必要
* getMonth()は英語の月名
* getMonth().getValue()で月の月の数字
私がノートパソコンを購入するまでの思考

#私がノートパソコンを購入するまでの思考

# 1. 目的
- 私が今後、端末を購入するときの判断材料にする。
- 適宜見直し。

# 2. 筐体
## 2.1 選択肢
- [ ] デスクトップ
- [x] ノートパソコン
- [ ] タブレット

## 2.2 理由

私が必要な機能は何か？優先することは何か？

- [x]  1. 文字入力（キーボード、マウス）　→　`デスクトップ`＞`○ノートパソコン`＞`（タブレット）`
- [x]  2. 持ち運ぶ（重量）　→　`タブレット`＞`○ノートパソコン`
- [x]  3. 画像編集、データベース（スペック）　→　`デスクトップ`＞`○ノートパソコン`
- [x]  4. 外部インターフェース　→　`デスクトップ`＞`○ノートパソコン`
- [x]  5. タッチパッド　→　`タブレット`＞`（○ノートパソコン）`
- [ ]  6. ゲーム（バトルロイヤル）　→　`デスクトップ`＞`（○ノートパソコン）`
- [ ]  7. パソコンを自作する（拡張性、柔軟性）　→　`デスクトップ`

# 3. OS(オペレーティングシステム)
## 3.1 選択肢
- [x] Windows
- [ ] MacOS
- [ ] その他

## 3.2 理由

私が必要な機能は何か？優先することは何か？

- [x]  1. ビジネス用途（会社で使用されているパソコン）　→　`Windows`
- [x]  2. Microsoft Officeの利用　→　 `Windows`　`（MacOS）`
- [ ]  3. OSリカバリのしやすさ　→　`MacOS`
- [ ]  4. iphoneアプリの開発　→　`MacOS`

# 4. 途中経過
ここまでの結果、私は、今回は`Windowsノートパソコン`を選択したい。
（古いが現在所有する`MacBook Air`がまだ使用できることも考慮した）

# 5. Windowsノートパソコン選定のためのスペック
参考 : [価格.com](https://kakaku.com/pc/note-pc/)

## 5.1 スペック
- [x]  CPU<BR>
        ・CPUスコア >= 7000<BR>
        　　・現在使用PCの2倍程度のスペックを想定<BR>
        　　・参考 : [PassMark : CPU Benchmarks](https://www.cpubenchmark.net/cpu_list.php#single-cpu)<BR>
        　　・現在使用PC1(2017) : Intel Core i5-7300U @ 2.60GHz CPUスコア : 3713<BR>
        　　・現在使用PC2(2016) : Intel Core i5-5250U @ 1.60GHz CPUスコア : 2458<BR>
        　　・現在使用PC3(2013) : Intel Celeron 847   @ 1.10GHz CPUスコア : 480<BR>

- [x]  画面<BR>
        ・サイズ：13インチ～14.5インチ（携帯性を考慮）
　　　　　・解像度：４K、FullHD
- [x]  OS<BR>
        ・Windows 10（64bit）
- [x]  メモリ<BR>
       ・メモリ>=16GB<BR>
- [x]  ストレージ<BR>
       ・SSD>=512GB
- [x]  光学ドライブ<BR>
       ・無し（重量を考慮し、必要時のみ外付けドライブを使用する。）
- [x]  グラフィック<BR>
       ・モバイル用ノートPCなので、こだわらないようにする。
- [x]  サイズ・重量<BR>
       ・1.3kg未満（携帯性を考慮）
- [x]  駆動時間<BR>
       ・10時間以上
- [x]  価格<BR>
       ・200,000円以下

# 6. 選定結果

上記条件で絞り込むと、50製品くらいに絞り込みできた。(2020/09/12時点)<BR>
[価格.com : 上記条件での絞り込み付き](https://kakaku.com/pc/note-pc/itemlist.aspx?pdf_Spec021=1&pdf_Spec107=13,18&pdf_Spec115=2&pdf_Spec301=13-14.5&pdf_Spec302=10-&pdf_Spec303=-1.3&pdf_Spec307=512-&pdf_Spec308=16-&pdf_Spec311=7000-&pdf_so=Spec311_a&pdf_pr=-200000)

上記条件で残った判断材料は、以下の通り。(2020/09/12時点)
　・CPUスコア：7000-14000
　・重量：0.747-1.29kg
　・価格：95,000-200,000円

あとは、CPU性能 or 重量 or 価格で、何を優先するかで決めていきたい。

# 以上
PHPで日付の範囲を定義して任意の間隔で処理をする

PHPで日付の範囲を定義して1時間毎など任意の間隔で処理をしたい時、例えば2020年1月1日0時0分0秒から2020年1月2日0時0分0秒まで1時間毎にループを回して何か処理をしたい場合の書き方。

## 結論

```php
<?php

$date_period = new DatePeriod(
  date_create('2020-01-01 00:00:00'),
  new DateInterval('PT1H'),
  date_create('2020-01-02 00:00:00')->add(new DateInterval('PT1H'))
);

foreach($date_period as $date) {
  echo($date->format('Y-m-d H:i:s') . "\n");
}
```

ここから実際に動かせます
http://sandbox.onlinephpfunctions.com/code/6590f911729eb743b45d73dbfafcc3eafd158581

## 解説

## DatePeriod

[DatePeriodクラス](https://www.php.net/manual/ja/class.dateperiod.php)を使うと日付の期間を定義できます。
これがTraversableとなっているのでforeachが回せます。

結論のコードを見て分かる通り、引数の1番目に開始日時、３番目に終了日時をDateTimeで指定します。
2番目には間隔を指定しますが、これは後述のDateIntervalクラスで表現します。
終了日時に1時間追加しているのは最後の日時がループに含まれないためです。

## DateInterval

[DateInterval](https://www.php.net/manual/ja/class.dateinterval.php)クラスを使うと日付（ループ）の間隔を指定できます。
1時間毎は`PT1H`と表現します。詳しくは[こちら](https://www.php.net/manual/ja/dateinterval.construct.php)に書いてあります。
HTML、CSSの実践の書き方

BEMとSMACSSを組み合わせる
※Sassを覚えたらSassも取り入れる


#【BEM】
```
{Block}__{Element}
{Block}-{Modifier}
{Block}__{Element}-{Modifier}
```

----- 例 -----

```
.archiveItem {
  margin-bottom: 20px;
}
.archiveItem__inner {
  display: flex;
  padding: 10px;
}
.archiveItem__thumb {
  margin-right: 20px;
}
```

#【SMACSS】

– Base
– Layout
– Module
– State
– Theme



----- 例 -----

```
body {}
html {}
 
/*---------- Layout ----------*/
 
.l-header {}
.l-footer {}
.l-main {}
.l-sidebar {}
 
/*---------- Module ----------*/
 
.button {}
.is-button-warning {} 
.label {}
.is-label-hidden {} 
.is-label-error {}
.heading {}

/*---------- Theme ----------*/
 
.dark-mode {}
.light-mode {}
```

※BEMが使えるものはレイアウトに入れ、BEMを使わないものはモジュールに入れる
Core Dataのtransformableな属性をセキュアに実装する

Core Dataのエンティティが持つ属性 (attribute) の型は整数、文字列、日付などいくつかの決まったものしかとることができませんが、Transformableを指定することで任意の型を `NSData` に変換して保存することができるようになっています。このとき保存したい型と `NSData` の変換を担うのがvalue transformerです。

Core Dataのtransformableを利用しているプロジェクトをXcode 12でビルドしたときに、以下のような警告が出るようになりました。

```
warning: Misconfigured Property: <NSManagedObjectのサブクラス>.<プロパティ> is using a nil or insecure value transformer. Please switch to NSSecureUnarchiveFromDataTransformerName or a custom NSValueTransformer subclass of NSSecureUnarchiveFromDataTransformer
```

これは、これまでのvalue transformerが `NSCoding` を使ったものであるため非推奨になっており、 `NSSecureCoding` をベースとした `NSSecureUnarchiveFromDataTransformer` に置き換える必要があるということです。

今回この警告の対応のために調べた、 `NSSecureUnarchiveFromDataTransformer` を使ってtransformableな属性をセキュアに実装する方法をまとめました。

## カスタムクラスが不要なパターン

`NSSecureUnarchiveFromDataTransformer` が扱える型は `allowedTopLevelClasses` で規定されていて、以下の通りです。

```
NSArray, NSDictionary, NSSet, NSString, NSNumber, NSDate, NSData, NSURL, NSUUID, NSNull
```

これらの型の組み合わせで表現できるもの、例えば文字列の配列 `[String]` の属性であれば、モデルエディタでTransformerの欄に `NSSecureUnarchiveFromDataTransformerName` を指定するだけでOKです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32084/fb964149-5c98-d732-7dff-aac647e18791.png" width=261>

## カスタムクラスが必要なパターン

上に挙げた型以外の `NSSecureCoding` に準拠した標準の型（`UIColor` など）や、`NSSecureCoding` に準拠した独自の型を使う場合は、 `NSSecureUnarchiveFromDataTransformer` を継承したカスタムクラスを実装する必要があります。

```swift
// Core Dataで利用するために @objc が必要です
@objc final class SecureValueTransformer: NSSecureUnarchiveFromDataTransformer {

    // クラス名をvalue transformerのnameとします
    static let name = NSValueTransformerName(rawValue: String(describing: SecureValueTransformer.self))

    // superが返すクラスの配列に追加する形で使用するクラスを指定します
    override static var allowedTopLevelClasses: [AnyClass] {
        super.allowedTopLevelClasses + [
            UIColor.self,
            NSTimeZone.self,
            CustomTypeA.self,
            CustomTypeB.self,
        ]
    }

    // value transformerを登録する処理です。Core Data Stackの初期化前に呼びます。
    public static func register() {
        let transformer = SecureValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }

}
```

モデルエディタではTransformerの欄に `name` で指定したクラス名を入力します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32084/de39fa24-439d-053f-5a0a-5fef635bb1ab.png" width=261>

最後にCore Data Stackの初期化前に以下を実行して、value transformerを登録します。

```swift
SecureValueTransformer.register()
```

## 参考リンク
- [NSSecureCoding and transformable properties in Core Data
](https://www.kairadiagne.com/2020/01/13/nssecurecoding-and-transformable-properties-in-core-data.html)
MacのVisual Studio Codeでデバイス間の同期設定を試してみた

# はじめに
仕事でもプライベートでもVisual Studio Codeを使っているのですが、できれば設定周りを同期したいと思っていました。
ふと、Visual Studio Codeの設定をみたところ、同期するための設定項目がありましたので、ここで紹介します。
同期の際には、GithubアカウントかMicrosoftのアカウントが必要になるので、事前に準備をしておくと、設定がスムーズかと思います。

# 設定を行った環境
Mac Catalina 10.15.6
Visual Studio Code August 2020 (version 1.49)

# 設定手順
1. 左下の設定ボタン -> 「設定の同期をオンにする...」をクリックします。
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/b9cac7a2-edb5-1a90-642e-22b919eaa31d.png)

2. 「オンにする」ボタンをクリックします。この時点ではプレビュー機能でした。
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/d8b2af1c-4a8c-53d8-15f4-d704ce37cb72.png)

3. デバイス間で同期するデータを選択して、「サインインしてオンにする」ボタンをクリックします。
同期するデータでは「設定、キーボードショートカット、ユーザースニペット、拡張機能、UIの状態」を選択することができます。
![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/7cf2539a-50af-86ae-776a-f476a854c2f9.png)

4. 同期するアカウントを選択します。MicrosoftアカウントかGithubアカウントを選ぶことができます。
ここでは、Githubアカウントを選択しました。
![img4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/7a0d05cb-ecf7-74fa-bc28-4c737fc32c12.png)

5. ブラウザが起動し、以下の画面が表示されるので、緑色のボタン「Continue」をクリックします。
![img5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/29d337c6-6905-fac8-f795-28704a5c8f7b.png)

6. 緑色のボタン「Authorize github」をクリックします。
![img6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/1eb446d9-fa75-9778-cd6b-5680ec11a469.png)

7. ダイアログの「Visual Studio Codeを開く」をクリックします。
![img7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/58bfdb3f-d530-45e4-cdc3-debf369692fb.png)

8. 「この拡張機能を再表示しません。」を選択して、「開く」ボタンをクリックします。
![img8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/a59e6c88-8fa2-ed15-0a97-45e0b2e01bae.png)

9. ダイアログが閉じるので、設定が完了となります。
![img9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/c815c598-5faa-5bbe-7e6d-a37eac3f2947.png)

# 設定を行った後は
左下のアカウントボタンをクリックすると、「設定の同期がオン」と表示され、設定の同期のオン・オフが確認できます。また「設定の同期がオン」をクリックすると、以下のメニューが表示されますので、必要に応じて、設定の同期を操作してみてください。
![img10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/980bfa97-d364-ba19-b290-a7c05ee91b4f.png)

設定の同期に関するメニュー
![img11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/ed5fd88f-2225-79e2-2327-df4c7f46cc10.png)

# おわりに
会社と自宅でVisual Studio Codeを使用している方は参考に同期設定をしてみてみると良いかと思います。
認証なしでSplunkダッシュボードを公開するには



# はじめに

Splunk で作ったダッシュボードを外部公開しよう。と思っても Splunkの認証が必要なのでSplunkアカウントを作って毎回ログインしてもらって。。など結構ハードルがあります。また大勢がログインして表示するとサーチ負荷がかかってしまいSplunkのサーチヘッドを拡張しないといけない。などの問題も発生してしまいます。

そこで、表示部分だけ切り出して公開する方法として、Webサーバを別途立ち上げて、そこにパネルとして表示するようにできます。
これはSplunkの埋め込み機能を利用します。

# 仕組み

Splunkダッシュボードをそのまま認証なしに公開することは残念ながらできません。そのかわりレポートとしてスケジュール実行した結果を iframe として外部から呼び出すことが可能です。


Splunk レポート作成　＝＞　スケジュール実行　＝＞　Webサイトから呼び出し(iframe)   
という流れです。

つまり、Webサイトからはサーチ条件を変えたりすることはできませんし、リアルタイム実行ではなく過去にスケジュール実行した結果を表示します。その代わりサーチが毎回走る訳ではなく過去の実行結果を表示するだけなので負荷が軽く、大勢の人にみてもらうことができます。

# Step1: レポート作成

サーチをレポートとして保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/ead62ab9-a9b7-462a-1b71-b6c3d405ffd7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/0cd0110c-19cf-4bdf-3e98-a575854fb746.png)


# Steap2: スケジュール設定

作成したレポートをスケジュール実行します。実行結果を呼び出して表示するため、この設定は必須です。設定の種類は複数あり、cron指定も可能なので 1分毎の実行なども可能ですが、サーバ負荷を考えるとある程度時間は開けた方がお勧めです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/f554a311-b02b-7cd9-49d4-4aa9d3cb8ac1.png)


# Step3: 埋め込み情報(iframe)の取得

レポートの画面で、「編集」ー「埋め込み」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/6f950b00-e9fd-d251-bc14-f1959b23da6d.png)

以下のようにiframe の情報をコピーします。Splunkサーバの情報や認証情報もここに含まれております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/0b06ace5-bdbb-453b-a5a4-8db3d6239026.png)


# Step4: Webサイトに先ほどコピーしたiframeコードを埋め込みます。

別途Webサーバを立ち上げて、以下のように先ほどのコードを埋め込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/44d3cd08-5e5b-ec8d-addc-c528a6b63033.png)

すると、このように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/b12f94c4-ad13-7030-b6d8-bdfcdf88746d.png)

もちろん、複数パネルも埋め込められます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/c2ba92ed-b55f-c637-e6c3-55657b4da7ef.png)


# 最後に

社内ポータルに埋め込んだり、サービス状況をモニタリングするサイトなどに埋め込むことで利用用途が大きく広がりますね。
Gatsbyノート6(Contentful-2)

### 学習内容

- Contentfulを使ってブログ詳細の情報を更新する


#### 1.gatsby-node.jsのSlugの生成を削除

```gatsby-node.js

//slugの生成
module.exports.onCreateNode = ({ node, actions }) => {
    const { createNodeField } = actions
    //MarkdownRemarkの場合に、slugを追加する
    if(node.internal.type === 'MarkdownRemark') {
        //basename関数を用いてslugを抽出
        const slug = path.basename(node.fileAbsolutePath, '.md')
        
        //nodeの再編成
        createNodeField({
            node,
            name: 'slug',
            value: slug
        })
    }
}
```

#### 2.Slugのqueryを書き換える(Contentfulから取得)

```gatsby-node.js

const path = require('path');

//ページの生成
module.exports.createPages = async ({ graphql, actions }) => {
    const { createPage } = actions
    //ブログ詳細ページ用のテンプレートの取得
    const blogTemplate = path.resolve('./src/templates/blogDetail.js')
    //slugの取得
    const res = await graphql(`
        query {
            allContentfulBlogPost {
                edges {
                    node {
                        slug
                    } 
                }
            }
        }    
    `)
    //各ページの生成
    res.data.allContentfulBlogPost.edges.forEach((edge) => {
        createPage({
            component: blogTemplate,
            path: `/blog/${edge.node.slug}`,
            context: {
                slug: edge.node.slug
            }
        })
    })
}
```

#### 3.blogDetail.jsを書き換える

- bodyのjsonをReactコンポーネントに変換してくれるプラグイン

https://www.npmjs.com/package/@contentful/rich-text-react-renderer

```
yarn add @contentful/rich-text-react-renderer
```

- リッチテキストに画像を追加する場合に必要なプラグイン

https://www.npmjs.com/package/@contentful/rich-text-types

```
yarn add @contentful/rich-text-types
```

```src/templates/blogDetail.js

import React from 'react'
import {graphql} from 'gatsby'
import Layout from '../components/layout'
import { Container, Button } from 'react-bootstrap'
// bodyのjsonをReactコンポーネントに変換
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'

export const query = graphql`
    query($slug: String!) {
        contentfulBlogPost(slug: {eq: $slug}) {
            title
            createdDate
            body {
                json
            }
        }
    }
`

function BlogDetail(props) {
    // リッチテキストに画像を追加する場合オプションを渡す
    // nodeTypeを指定することで、nodeTypeごとに処理を加えることができる
    const options = {
        renderNode: {
            "embedded-asset-block": (node) => {
                return (<img
                width="100%"
                src={node.data.target.fields.file['en-US'].url}
                alt={node.data.target.fields.title['en-US']} />)
            }
        }
    }
    return (
        <Layout>
            <Container style={{maxWidth:640}} className="pt-4">
                <h1>{props.data.contentfulBlogPost.title}</h1>
                <p>{props.data.contentfulBlogPost.createDate}</p>
                {documentToReactComponents(props.data.contentfulBlogPost.body.json, options)}
            </Container>
            <Container className="text-center">
                <Button href="/" variant="outline-info">一覧へ戻る</Button>
            </Container>
        </Layout>
    )
}

export default BlogDetail
```
Nginx で VirtualHost を使う

Nginx で VirtualHost を使う方法です。

次の例では、ekzemplaro.org と corona.ekzemplaro.org を受け付ける設定です。
どちらも、Let's Encrypt を使い、http は https にリダイレクトされます。


```text:/etc/nginx/nginx.conf
#
worker_processes  1;

error_log  /var/log/nginx/error.log;

events {
	worker_connections  1024;
}


http {
	include		 mime.types;
	default_type  application/octet-stream;

	sendfile  on;

	keepalive_timeout  65;
	types_hash_max_size 4096;
	server_names_hash_bucket_size 128;

	server {
		listen		 80;
		server_name	  ekzemplaro.org;
		access_log  /var/log/nginx/access.log;

		return 301 https://$host$request_uri;
		}

	server {
		listen  443 ssl;
		server_name	  ekzemplaro.org;

		location / {
			root	/var/www/html;
			index  index.html index.htm;
		}



ssl_certificate		/etc/letsencrypt/live/ekzemplaro.org/fullchain.pem;
ssl_certificate_key	  /etc/letsencrypt/live/ekzemplaro.org/privkey.pem;

	 }

server {
	listen	80;
	server_name corona.ekzemplaro.org;
	access_log  /var/log/nginx/corona.access.log;

	return 301 https://$host$request_uri;

	}

server {
	listen  443 ssl;
	server_name	  corona.ekzemplaro.org;

	access_log  /var/log/nginx/corona.access.log;

	root /var/www/html/corona;

ssl_certificate		/etc/letsencrypt/live/corona.ekzemplaro.org/fullchain.pem;
ssl_certificate_key	  /etc/letsencrypt/live/corona.ekzemplaro.org/privkey.pem;

	}


}
```

## 設定ファイルの確認

```text
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

## サーバーの再起動

```bash
sudo systemctl restart nginx
```

## Tips

server_name が間違っていても、

```bash
sudo nginx -t
```

は、successful　となります。

## 関連ページ
[Apache2 で VirtualHost を使う](https://qiita.com/ekzemplaro/items/5520bf4f840e4140cc69)
Rails：createアクションの仕組み

#動機
newとcreateの役割に困惑したためのメモ作成

#new
新しく作成する場合は
new.html.hamlとnewアクションがまず使用される

#create
newの中のformで作成した内容を元にDBへ登録するアクションがcreate

以下のコードが一連の流れです。

```
def create
    @task = Task.new(task_params)
    if @task.save
      redirect_to task_path(@task), notice: 'Task is create'
    else
      render :new
end
```


##データの取得

```
@task = Task.new(task_params)

private
  def task_params
    params.require(:task).permit(:title, :content)
  end
```

newで取得した内容を@taskに引数として渡している
引数にはprivateメソッドで取得した値をいれる

requireは必要という意味
permitは許可という意味
なので:taskモデルの:titleと:contentは許可するけど他の値は許可しないよというようなデータを取得している(ストロングパラメータ)

##save

```
if @task.save
      redirect_to task_path(@task), notice: 'Task is create'
    else
      render :new
```

取得したデータが保存できたら
showページに遷移する
できなかったらnewページに遷移する

###重要
createアクション内もインスタント変数にしている理由は
createからnewページへ遷移する際newページで使用されるインスタンス変数はcreateアクション内にインスタンス数があればこれを利用できる


すなわち
保存されなかったデータも残したままnewページを呼び出すことができる
【Rails】LINEBotでPush送信

# 概要
RailsからLineBotのPush送信します
以下のように、任意のタイミングで送信するやつです
![Screenshot_20200912-131255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199110/6b0c36c0-c938-83c3-f814-769a2267786f.png)


# LINEBotの作成
記事がたくさんあるので、そちらを参照してください
例えば、以下のような記事があります

[LINE BOTの作り方を世界一わかりやすく解説（１）【アカウント準備編】](https://qiita.com/yoshizaki_kkgk/items/bd4277d3943200beab26 "Qiita")

# RailsからLINEBotでPush送信
1. Gemfileでライブラリ`line-bot-api`をインストールしておいてください
2.  `ENV["LINE_CHANNEL_SECRET"]`、`ENV["LINE_CHANNEL_TOKEN"]`は、herokuなど、サーバ側で、設定する必要があります。この後、説明します
3. 自分のuser_idは、チャンネル基本設定->あなたのユーザーID、から確認できます
4. push_messageがlinebotでpush送信する部分です

```ruby:linebot_controller.rb
class LinebotController < ApplicationController  
    require 'line/bot'  # gem 'line-bot-api'  
     
    def client  
      @client ||= Line::Bot::Client.new { |config|  
        config.channel_secret = ENV["LINE_CHANNEL_SECRET"]  
        config.channel_token = ENV["LINE_CHANNEL_TOKEN"]  
      }  
    end  
     
    def push
        
        message={
            type: 'text',
            text: "hello"
           }
        user_id =  '[送信先のLINEアカウントのユーザID]'
        response = client.push_message(user_id, message)
    end

  end  
```
# Railsアプリをherokuにデプロイ
Railsアプリのデプロイの記事がたくさんあるので、そちらを参照してください
例えば、以下のような記事があります

[HerokuにRailsアプリをデプロイする手順](https://qiita.com/NaokiIshimura/items/eee473675d624a17310f, "Qiita")

この時、以下のように、チャネル基本設定->チャネルシークレット、Messaging API設定->チャネルアクセストークン、をherokuに必ず設定してください

```
$ heroku config:set LINE_CHANNEL_SECRET="[チャネルシークレット]"
$ heroku config:set LINE_CHANNEL_TOKEN="[チャネルアクセストークン]"
```

# 結果
herokuにデプロイした、Railsアプリのlinebot_controller.rbのアクションpushを実行します
以下のように「hello」がpush送信できました
![Screenshot_20200912-131255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199110/6b0c36c0-c938-83c3-f814-769a2267786f.png)
PCに接続できない環境でもLogcatのログを取得したい時に使えるアプリ「Logcat Recorder」の紹介

# 背景

Androidアプリのテストで、Logcatに出力されたログを収集したい時、方法として

- Android StudioのLogcatを利用する
- 端末とPCをUSB接続するなどしておき、`adb logcat -v time > log.txt`コマンドを叩いておく

があると思います。
ですが、耐久試験で1日以上放置しないといけなかったり、PCの環境に不安がある場合に、上記の方法だとどうしても難しい場合もあります。
そんな時に使えるアプリ「[Logcat Recorder](https://apkpure.com/jp/logcat-recorder/com.namakerorin.neko)」を紹介したいと思います。

# アプリの概要

https://apkpure.com/jp/logcat-recorder/com.namakerorin.neko
からの引用です。

> PCに接続できないような環境下やlogを常時取得しておきたい局面などで重宝します。

>■概要
・logcat出力をSDカードなどのストレージに出力します (任意のパスに切り替え可能です)
・logcatの出力形式は"-v threadtime" です
・logファイルは時間(1分～6時間)とサイズ(500KB～100MB)で自動的に分割します
・Broadcast Intentをlogに出力します (Battery、Telephony、Configulation、Wi-fi、Bluetooth、Mediaなど)
・logの全体サイズの制限できます (100MB～4GB、制限なし)
・logを参照したり削除ができるファイラーがついています

# Android端末の環境

環境は以下の通りです。

- 端末名: Xperia 10 Ⅱ
- OS: Android 10

# 導入方法

https://apkpure.com/jp/logcat-recorder/com.namakerorin.neko
からAPKファイルをダウンロードします。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/f84756d0-dedc-8181-fd12-904ede9e88da.png)

ダウンロードしたら、テストしたい端末とUSB接続するなどしておき、以下のコマンドでインストール&権限付与します。

```
adb install 'Logcat Recorder_v1.0.2_apkpure.com.apk'
adb shell pm grant com.namakerorin.neko android.permission.READ_LOGS
```

導入後、アプリを起動すると、以下のような権限許可の画面が出てきます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/7843174d-11a2-b49a-60f9-01dc859f77b1.jpeg alt=2.jpg width=300>

両方とも許可したうえで「続行」をタップします。
すると、以下のようなダイアログが出てきます。（うろ覚えですが、Android 8では出てこなかったと思います。どのバージョンから出るようになったかは不明）

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/3e30bd1a-2174-2e4d-b40a-0cc8e73884ad.jpeg alt=3.jpg width=300>

いったん「OK」をタップして次に進みます。
導入はこれで完了です。

# 使い方

アプリを有効にするには、「Record logcat」のトグルをONにするだけです。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/963a4792-e0c5-6250-7a5d-821e1aa11b65.jpeg alt=4.jpg width=300>

ONにすると、ステータスバーのところにアプリアイコンが表示されます。
このアイコンが表示されている間は、ログが保存され続けることになります。
OFFにすると保存が中断されます。

# 保存されたログの確認方法

「Log viewer」をタップすると、以下の画面に遷移します。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/e05e81e8-8af3-702c-d5f0-6937afdf8799.jpeg alt=5.jpg width=300>

日時ごとにどのくらいのデータ量が保存されているかが確認できます。
チェックボックスをタップすると、画面が以下のように変化し、ゴミ箱ボタンをタップするとログを削除することができます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/c571bd92-98d6-44b5-34e7-b06b55abaa38.jpeg alt=6.jpg width=300>

日時のテキストをタップすると、さらにテキストファイルが表示されます。
先ほどと同様、チェックボックスをタップすると、画面が以下のように変化し、ゴミ箱ボタンをタップするとログを削除することができます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/6c1ac90d-601b-31ad-716b-9086f067f76a.jpeg alt=7.jpg width=300>

また、ファイル名をタップすると別アプリからファイルの中身を閲覧することができます。（私の環境ではエラーが出て表示できませんでした。。）

保存されたファイル群をPCにコピーすることもできて、その場合は以下コマンドを実行します。

```
adb pull /storage/emulated/0/neko/ [PC上の保存したい場所]
```

# まとめ

PCに接続できないような環境下や、耐久試験などでLogcatのログを取得し続けたいときに使えるアプリ「Logcat Recorder」を紹介しました。
ただし、Android 10以降ではうまく動作しない可能性がありますので注意してください。
（もっといい方法があれば教えてくださると嬉しいです）
ドライブバイダウンロード(Drive-by download)


応用情報技術者平成29年秋期 午前40

ドライブバイダウンロード攻撃の説明はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/7d871512-8618-bd6b-c7d1-a131b00587f2.png)



１、ドライブバイダウンロードは、(Drive-by download)
Webサイトにマルウェアやウイルスを仕込んでおき、アクセスしてきた利用者の知らぬうちに、それらを自動ダウンロード又は実行させる攻撃です。
この攻撃単体で仕掛けられるほか、Gumblar攻撃や水飲み場型攻撃などのように他の攻撃の一部に組み込まれて使用されるケースもあります。

・Gumblar（ガンブラー）とは「Webサイト改ざん」と「Web感染型ウイルス（Webサイトを閲覧するだけで感染するウイルス）」を組み合わせて、多数のパソコンをウイルスに感染させようとする攻撃手法（手口）のことである。

・水飲み場型攻撃とは、watering hole attack
攻撃対象となる組織のユーザーが普段アクセスするウェブサイト（つまり、水飲み場）を特定し、そのサイトを改ざんし、ドライブバイダウンロード攻撃（Webブラウザーを通じて、ユーザーに気付かれないように悪意のあるソフトウェアをダウンロードさせる攻撃手法）などを利用してマルウェアに感染させようとする標的型攻撃の一種です。

水飲み場型攻撃は、IPアドレスなどから訪問者の所属組織や属性を判定し、攻撃対象を特定することもあります。そのため、標的以外の利用者がサイトに訪れても何も起きないこともあり、攻撃が発覚しにくいという特徴もあります。


２、autorun.infを悪用して感染を試みるウイルスの説明
PCにUSBメモリが接続されたとき，USBメモリに保存されているプログラムを自動的に実行する機能を用いてマルウェアを実行し，PCをマルウェアに感染させる。

・autorun.inf
PCにCDやUSBが接続されたときに自動で起動するファイル名を記述するための設定ファイル

３、ランサムウェアの説明　Ransomware
PCに格納されているファイルを勝手に暗号化して，復号することと引換えに金銭を要求する。


４、ウォードライビング(War Driving)の説明
不正にアクセスする目的で，建物の外部に漏れた無線LANの電波を傍受して，セキュリティの設定が脆弱な無線LANのアクセスポイントを見つけ出す。


参照：
水飲み場型攻撃とは？
https://blogs.mcafee.jp/watering-hole-attack-prevention#:~:text=%E6%B0%B4%E9%A3%B2%E3%81%BF%E5%A0%B4%E5%9E%8B%E6%94%BB%E6%92%83%E3%81%A8%E3%81%AF%E3%80%81%E6%94%BB%E6%92%83%E5%AF%BE%E8%B1%A1%E3%81%A8%E3%81%AA%E3%82%8B,%E3%81%A8%E3%81%99%E3%82%8B%E6%A8%99%E7%9A%84%E5%9E%8B%E6%94%BB%E6%92%83
addEventListenerの第三引数ってなんだ？


下記の参考書を進めてきて、ついに7章に突入し読了が近づいてきた。
[JavaScript本格入門　山田祥寛著](https://gihyo.jp/book/2016/978-4-7741-8411-1)

そんな中ずっと気になっていたことがあった。

```
//記入例
document.getElemetById('hoge').addEventListener('click',function() {
},false);
```

そう、**addEventListenerの第三引数、falseってなんだ？？**

~~「7章まできて、そんなこともわかっていなかったのか!!」~~



本書では、addEentListenerメソッドについて下記のように記載されていた。


>elem.addEventListener(type, listener, capture)
>
>elem:要素オブジェクト
>type:イベントの処理
>listener:イベントに応じて実行すべき処理
>capture:イベントの方向
>[引用元:JavaScript本格入門 p299　山田祥寛著](https://gihyo.jp/book/2016/978-4-7741-8411-1)

今回知りたいのは、第三引数、captureについてだ。

captureはイベントの方向を指定するためのものらしい。

**「イベントの方向とはなんぞや」**と言うことで、本書で指定されたp347を見ると、イベントの伝搬つまり、イベント処理が呼び出されるまでのプロセスが関係しているっぽい（むずよー）。


まず、イベントの伝搬は次のようなフェーズを辿っているそうだ。

1.キャプチャフェーズ
2.ターゲットフェーズ（イベント発生!）
3.バブリングフェーズ

**通常(第3引数がfalse)の場合**だと、「イベントの発生元から上位ノード」へと処理が進む、つまり**バブリングフェーズ**でイベントは処理されるそう。


だから、この**第三引数をtrue**にすることで、「上位ノードからイベントの発生元」と方向が逆になり、
**キャプチャフェーズ**でイベントが処理されるようになると言うことだそうだ。


今回の目的であった、addEventListenerメソッドの第三引数の意味は最初よりはイメージできたが
実際に現場でこれらをどういった場面で使い分けるのかと行ったことは、まだイメージできなかった。
まあ、それは今後わかっていけばいいかなー笑。~~これだから最近の若者は...。~~
SIEM(Security Information and Event Management)


応用情報技術者平成29年秋期 午前38

SIEM(Security Information and Event Management)の特徴はどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/9f43aeb6-f322-4c65-b86f-10fd252f0d65.png)


１、SIEM(Security Information and Event Management)は、
OS、データベース、アプリケーション、ネットワーク機器など多様なソフトウェアや機器が出力する大量のログデータを分析し、異常があった場合に管理者に通知したり対策を知らせたりする仕組みです。日本語ではセキュリティ情報およびイベント管理と訳されます。

・SIEM
SIEM（シームと読む）は「SIM」（Security Information Management）と「SEM」（Security Event Management）を組み合わせた言葉（ガートナーによる）だ。

　SIMはいわゆる「統合ログ管理」のうちセキュリティ領域のログを対象とした仕組みのことをいい、さまざまなネットワーク機器やホストシステムが出力するセキュリティイベントログおよびシステムユーザーの利用ログなどを蓄積し、さまざまな視点から検索、分析を行う。

　SEMは、同様にさまざまな機器からのログを収集、蓄積することは同じだが、分析をリアルタイムに行う点が異なる。



２、ファイアウォールやIPSなどの特徴
DMZを通過する全ての通信データを監視し，不正な通信を遮断する。


・IDSは
Intrusion Detection Systemの略称で、不正侵入検知システムとも呼ばれます。

インターネットに公開するサービスでは、それに対する通信はファイアウォールでは接続許可の扱いとなるため、正常な通信と異常な通信は区別なくアクセスされることになります。

そこで、IDSを設置することで、通信を監視します。
また、もし異常があれば管理者へ通知することで、異常な通信をブロックするなどの対処をするきっかけ（トリガー）となります。

・IPS
IPSはIntrusion Prevention Systemのことで、不正侵入防止システムとも呼ばれます。

IPSはIDSより一歩進んで、異常な通信があれば、管理者へ通知するだけでなく、その通信をブロックするところまで動作します。
したがって、管理者が異常に気づいてから対処するのと異なり、迅速な対処が可能となります。


３、SNMP(Simple Network Management Protocol)の特徴
サーバやネットワーク機器のMIB(Management Information Base)情報を分析し，中間者攻撃を遮断する。
SNMPにはRMON(Remote network MONitoring)という通信状況を監視するMIBがあります。


４、Cisco社のNetFlowの特徴
ネットワーク機器のIPFIX(IP Flow Information Export)情報を監視し，攻撃者が他者のPCを不正に利用したときの通信を検知する。


参照：
https://www.ap-siken.com/kakomon/29_aki/q38.html

ディジタルフォレンジックス　収集、検査、分析、報告
https://qiita.com/lymansouka2017/items/f28396af226b46c56618


https://qiita.com/lymansouka2017/items/8e842add016498242661

IDSとIPSの違いとは
https://www.shadan-kun.com/blog/measure/303/
SwiftUI用のジョイスティックUIライブラリ OMJoystickの使い方

[OMJoystick](https://github.com/tichise/OMJoystick)はSwiftUI用のジョイスティックUIライブラリです。CocoaPodsとSwift Package Managerからダウンロードできます。

### 動作イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4019/08f6f1e3-439b-a813-9cdd-d5e87930e9b0.png)

### インストール方法
CocoaPodsでPodfileに下記のように記述します。

`pod 'OMJoystick'`


### 動かし方

以下のコードで、デフォルト設定のまま動かすことができます。

```swift
import SwiftUI
import OMJoystick

struct ContentView: View {
    var body: some View {
        OMJoystick(colorSetting: ColorSetting()) { (joyStickState, stickPosition) in
        }
    }
}
```

アイコンやサイズ、色などの見た目を変えたい場合は、下記のように設定します。

```swift

import SwiftUI
import OMJoystick
import SFSafeSymbols

struct ContentView: View {        
    let iconSetting = IconSetting(
        leftIcon: Image(systemSymbol: .arrowLeft),
        rightIcon: Image(systemSymbol: .arrowRight),
        upIcon: Image(systemSymbol:.arrowUp),
        downIcon: Image(systemSymbol: .arrowDown)
    )
    
    let colorSetting = ColorSetting(subRingColor: .red, bigRingNormalBackgroundColor: .green, bigRingDarkBackgroundColor: .blue, bigRingStrokeColor: .yellow)
    
    var body: some View {
        GeometryReader { geometry in
            VStack(alignment: .center, spacing: 5) {
                OMJoystick(isDebug: true, iconSetting: self.iconSetting,  colorSetting: ColorSetting(), smallRingRadius: 70, bigRingRadius: 120
                ) { (joyStickState, stickPosition)  in
                    
                }.frame(width: geometry.size.width-40, height: geometry.size.width-40)
            }
        }
    }
}
```
Pythonでデスクトップのパスを得る

PythonでmacOSとWindows共通でデスクトップのパスを得る方法。

いろいろありますが、os.path.expanduserを使うのが簡単です。

```get_desktop.py
import os
desktop_dir = os.path.expanduser('~/Desktop')
print(desktop_dir)
```

環境変数から取得するのも良い方法ですが、その場合、OS判定が必要です。

```get_desktop2.py
import os
if os.name == 'nt':
    home = os.getenv('USERPROFILE')
else:
    home = os.getenv('HOME')
desktop_dir = os.path.join(home, 'Desktop')
print(desktop_dir)
```

以上、簡単な紹介でした。
CRL(Certificate Revocation List，証明書失効リスト)

応用情報技術者平成29年秋期 午前36

認証局が発行するCRLに関する記述のうち，適切なものはどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/e8673b5e-711a-cb27-5f28-e010be0178eb.png)


１、CRL(Certificate Revocation List，証明書失効リスト)は、
　・有効期限内であるにも係らず、
　・秘密鍵の漏えい、紛失、証明書の被発行者の規則違反などの理由により
　・失効したディジタル証明書が列挙されたリストです。
CRLには、失効した証明書の
　・シリアル番号と
　・失効日時が登録されています。

CRLに登録されている証明書は有効期限の満了時点でCRLから抹消されます。

※Revocation　失効、廃止、取り消し


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/5dae733b-4683-be55-bdcc-d150d0504610.png)


２、OCSP(Online Certificate Status Protocol)に関する記述
鍵の漏えい，失効申請の状況をリアルタイムに反映するプロトコルである。



参照：

https://www.ap-siken.com/kakomon/29_aki/q36.html

サーバ署名の検証
https://www.e-tax.nta.go.jp/shomeisho/kakunin4.htm
競技プログラミング用のXORの性質

# はじめに
AtCoderのXOR (排他的論理和)の問題を解く時に使う性質をメモします。

# XORの性質

```cpp:
x ^ y = y ^ x //交換則
```

```cpp:
x ^ x = 0 //自分自身は0になる
```

```cpp:
x ^ 0 = x //0を作用させても変わらない
```

```cpp:
(2*a) ^ (2*a + 1) = 1 //任意の偶数について成り立つ
```

# まとめ
XORの演算をメモしました。
これ以外で重要な性質があったら、随時書き足します。
jQueryプラグインでオリジナルのダイアログを表示する方法

#デフォルトで表示
特にカスタマイズせず、confirm()で表示すると下記のような表示になります。
![初期ダイアログ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/472aaacb-efab-a296-157e-7601b1ab58ff.png)
OK/キャンセルの2択だけ選択させたい場合であれば、初期ダイアログで事足りますが、
ボタンや選択肢を追加したい場合、カスタマイズする必要があります。

あと、個人的に初期デフォルトだとIPが表示されてかっこ悪い印象を持ちます:sweat_smile:
このあと、カスタマイズする方法を説明します。

## 準備
オリジナルのダイアログを表示するにはjQuery UIのDialogプラグインを用います。
jQuery UIに必要なファイルは下記3つになります。

+ jQueryのJavaScriptライブラリ
+ jQuery UIのJavaScriptライブラリ
+ jQuery UI用のCSSテーマファイル

```
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- jQuery UI -->
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
```

#オリジナルのダイアログで表示
今回はダイアログ上に、選択項目を追加していきます。

##HTML側の記述
HTML側ではダイアログを呼び出すボタン、ダイアログの内容を記述します。

```
<!--ダイアログを呼び出すボタン-->
<button id="btn">ダイアログ表示</button>
 
<!--ダイアログの内容-->
<div id="dialog" title="同意書">
  <!--ラジオボタンを配置-->
  <label><input type="radio" name="test" value="1" checked> 選択肢1</label><br />
  <label><input type="radio" name="test" value="2"> 選択肢2</label><br />
  <!--チェックボックスを配置-->
  <label><input type="checkbox" value="1">上記記載事項に同意します</label>
</div>
```

##Dialogのオプション項目
JavaScriptでダイアログを呼び出す処理について記述していきますが、
__呼び出し時には必ずオプション項目を定義する必要があります。__

ダイアログのオプション項目は下記の通りです。

| オプション | 内容 | 
|:-----------|:------------|
| autoOpen| 初期表示にダイアログを開くか設定(初期値:true)|
| Width| ダイアログの横幅を指定。単位はピクセル(初期値:300)|
| modal| モーダルダイアログにしたい場合はtrueに設定する(初期値:false)。背景が少し暗くなる。| 
| buttons| 記述形式は次の通り。<br>{text:(ボタン名), click:(処理)} <br>click以外のイベントも定義可能|

##JavaScript側の記述
```
$(function(){
    //ダイアログの初期設定
    $("#dialog").dialog({
        autoOpen: false, //自動で開かないように設定
        width: 500,       // 横幅のサイズを設定
        modal: true,  //モーダルダイアログにする
        buttons: [
            {
                text: "戻る",
                click: function(){
                    // ダイアログを閉じる
                    $(this).dialog("close");
                }
            },
            {
                text: "次へ",
                click: function(){
                    // ページ遷移
                    window.open('https://qiita.com/tamakiiii', '_blank');;
                }
            }
        ]
    });

    $("#btn").click(function(){
        //ダイアログの呼び出し
        $("#dialog").dialog("open");
    })
});
```
表示したときのダイアログはこんな感じです
![オリジナルダイアログ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/6885ba0e-b94a-8540-f531-f61d73d2cbfa.png)

#参考
[jQuery UI を用いてオリジナルのダイアログを実装する方法！独自のボタンや選択肢も簡単に追加できる！](https://webllica.com/jquery-ui-dialog//)
localStrageで半永久保存のやり方

webブラウザの機能のlocalStrageについてです。

まず、localStrangeをなんなのか見てみましょう

見方についてはchromeの検証ツール→アプリケーション→localStrage→fileで見ることができます。

![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708552/147e29b8-c074-2d05-ff1c-e6f5e5cba164.png)

では、この機能について見ていきましょう

開いたらキーと値というものがあると思いますが、これは、keyとvalueでこれらをここに格納できるんです。

格納するだけだったらオブジェクトと変わりませんよね。ですが、これはページを閉じたりリロードをしたりしてもずっと保存しておきたい値を格納できるんです。


使い道は（どのページを見ただとか、どの商品にお気に入りボタンを押したなど）など様々です。

cookieとあんまり変わらないですが、容量や保存期間が少し違います

ですが、ここに格納するには、一つ条件があります。

それは、すべて文字列で書かなきゃいけないんです。

例えば、配列やオブジェクトをそのままlocalstrageに保存すると
"[Object object]"のように意味不明な形で保存されます。

これを解決するにはjsonでオブジェクトを文字列にしなければいけません。

やり方は

```js
json.stringify([1,2,3])
```

とすると

```js
"[1,2,3]"
```
と文字列になりlocalStrageに保存できるようになります。

なお、json.stringifyは配列の中身が多すぎて見れないときなどに見れるようにするためにもつかわれます。

ちなみに、json型が使いづらくて元の形に戻したい場合は
```js
json.parse
```
でもとに戻せます。

##localStrageに文字列を保存する方法

```js
localStrage.setItem("key","value")
```

```js
//その2：オブジェクトのプロパティとして保存するパターン
localStorage.saveKey = '保存する値';
```
これで格納できます。

また、値を返したいときは

```js
localStrage("key")
```

複数格納の場合

```js
var obj = {
      last : tarou,
      first : yamada
    };
var obj = JSON.stringify(obj);
localStorage.setItem('Key', obj);
```


取り除く場合

```js
localStorage.removeItem('Key');
```
初期化

```js
localStorage.clear();
```