OmniAICreator/Qiita-1.07M huggingface dataset:
特定のパッケージを使用しているローカルリポジトリを探す

## はじめに

この記事は、grepコマンドによる依存パッケージの調査方法についてのメモです。

GitHubの[Dependabot](https://docs.github.com/ja/free-pro-team@latest/github/managing-security-vulnerabilities/viewing-and-updating-vulnerable-dependencies-in-your-repository)など、依存パッケージの脆弱性警告ツールが普及しました。しかしその警告に従い、複数のリポジトリをまたいで依存パッケージを調査するのは骨の折れる作業です。

こうした状況で便利なコマンドがgrepです。grepは多くの環境に移植されていますので、使い方を一度憶えてしまえば役立つ資産となります。

## grep

grepは正規表現によりファイルを検索するUNIXコマンドです。

[man page of grep](https://linuxjm.osdn.jp/html/GNU_grep/man1/grep.1.html)

このコマンドを利用すれば、ファイルを横断した本文検索ができます。

### 使用例1 : 特定の語句を含むファイルを検索する

```zsh
grep -lr <pattern> --include="package.json" --exclude-dir=node_modules ./*
```

このコマンドの内容を書き下すと、以下のようになります。

カレントディレクトリ`./*`以下で、ファイル名`package.json`の`<pattern>`を含む行を探す。ただしディレクトリ`node_modules`は除外する。

使用しているオプションは以下の通りです。

- `-r` : ディレクトリを再帰処理（デフォルトではディレクトリ直下のファイルを検索する）
- `-ｌ` : ファイル名のみを表示（デフォルトでは該当する行も同時に表示する）

### 使用例2 : 特定の語句を含まないファイルを検索する

```zsh
grep -lrL <pattern> --include="package.json" --exclude-dir=node_modules ./*
```

使用例1に`-L`オプションを追加すると、`<pattern>`文字列を含まないファイルを検索できます。たとえばpackage.jsonにあるべきフィールドが指定されていないプロジェクトを一括で探し当てられます。

参考記事 : [特定の文字列を含まないファイルを検索する](https://qiita.com/ritukiii/items/4945d61df4a99ebe9a4e)

他にも検索パターンやオプションを変更すれば、grepは様々な問題の解決に役立ちます。皆様の問題に合わせてオプションを変更してみてください。

以上、ありがとうございました。
ユーザのタイムゾーンを数式で求める方法

質問の回答を検証している時にみつけました。なかなか面白い記事です。

[How do I access the user's timezone in a formula field?](https://trailblazers.salesforce.com/answers?id=9063A000000suLPQAY)

このソリューションは、Salesforceの2つのすぐに使用できる関数、つまりDATEVALUEとDATETIMEVALUEの間の紛らわしい不整合を利用しています。

前者はユーザーのタイムゾーンで評価され、後者はGMTとして評価されます。この不整合を利用して、次のようにユーザーのタイムゾーンを導き出すことができます。このコードを「UserTimezoneOffset」という名前の新しい数式フィールドに貼り付けます。

```
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 00:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 01:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 02:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 03:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 04:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 05:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 06:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 07:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 08:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 09:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 10:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 11:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 12:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 13:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 14:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 15:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 16:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 17:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 18:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 19:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 20:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 21:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 22:00:00")) - TODAY()) + 
(DATEVALUE(DATETIMEVALUE(TEXT(TODAY())+" 23:00:00")) - TODAY())
```

能力の高い人がいるものです。世界は広いなぁ。
Pythonで学ぶアルゴリズム　第3弾：基数変換

# #Pythonで学ぶアルゴリズム< 基数変換 >#

##はじめに
基本的なアルゴリズムをPythonで実装し，アルゴリズムの理解を深める．
その第3弾として基数変換を扱う．ついでに，ビット演算についても触れる．

##基数変換
10進数を2進数に変えたり，その逆であったりと基数(扱う数字の数)を変換すること．
それらについて実装し，基数変換の復習を行う．

##基数変換 ver.1
まずは，原理に基づいて非常に簡単に10進数を2進数に変換するプログラムを実装する．
コードは次に示す．
#####コード

```python:radix_conversion1.py
"""
2020/12/16
@Yuya Shimizu

基数変換 ver.1
10進数 → 2進数
"""
a = 18
result = ' '

# 10進数 → 2進数
while a > 0:
    result = str(a%2) + result
    a //= 2

print(result)
```

#####出力
```
10010 
```
2進数への変換は10進数で表された数字を2で割っていき，商が0となるまで繰り返した後，その余りを後ろから並べることで，完了する．上記のプログラムでは，```while a>0:```で繰り返しを表現，文字の合成については後ろから並べられるように，```str(a%2)```を前にして合成を行っている．
ほかの進数への変換も同様に行うことができるので，ver.2では関数にまとめて，ほかの進数にも変換してみた．ただし，単純なつくりでしかないため，10進数までのものしか表現できない．

##基数変換 ver.2
関数にまとめて，10進数をほかの進数にも変換するプログラムを実装する．
コードは次に示す．
#####コード

```python:radix_conversion2.py
"""
2020/12/16
@Yuya Shimizu

基数変換 ver.2
10進数 → n進数
"""

# 簡単な関数
def convert(n, base):
    result = ' '

    # 10進数 → n進数
    while n > 0:
        result = str(n%base) + result
        n //= base

    print(result)


n = 18
convert(n, 2)
convert(n, 4)
convert(n, 8)

# 用意されている10進数と2進数に関する関数
print(bin(n))

```

#####出力

```
10010 
102 
22 
0b10010
```
関数の中のプログラムはver.1とほぼ変わらない．ただ，2進数への変換はすでに用意された関数でより簡単に変換することができる．```bin()```である．出力の上端・下端を見れば，確かに2進数に変換されていることが分かる．0bについては後述する．つづいて，ver.3では，2進数を10進数に戻すプログラムを示す．

##基数変換 ver.3
2進数を10進数に戻すプログラムを実装する．
コードは次に示す．
#####コード

```python:radix_conversion3.py
"""
2020/12/16
@Yuya Shimizu

基数変換 ver.3
2進数 → 10進数
"""

# 簡単な関数
def Re_convert(n):
    result = 0
    # 2進数 → 10進数
    for i in range(len(n)):
        result += int(n[i]) * (2**(len(n) - i - 1))

    print(result)


n = '10010'
Re_convert(n)

# 用意されている関数(引数が文字型)
print(int(n, 2))    

# 別の方法
a = 0b10010 #0bをつけることで整数型として扱われる←結果は上と同じ
print(a)

```

#####出力

```
18
18
18
```
すべて同じ結果が得られることが分かる．先ほど同様，用意されている関数```int()```を使うことができる．第一引数を文字型で表した数字，第二引数が第一引数が2進数であることを示す．そしてint(整数)型として10進数に変換される．
また別の方法もあり，0bをつけることで，整数型として扱われることになる．先ほど，文字型で指定していたが，0bの後ろに2進数を表すと，先ほどの処理を挟まずして，```print```したときに10進数を示してくれる．


##ビット演算
論理回路でよく用いられる演算だが，これらについての処理も同様な関数を用いて行うことができるので，ついでに見ておく．ここでは，論理積，論理和，排他的論理和，左シフト，右シフトを扱う．
コードは次に示す．
#####コード

```python:bit_Operation.py
"""
2020/12/16
@Yuya Shimizu

ビット演算
"""
a = 0b10010
b = 0b11001

#ビット反転
print(bin(~a), bin(~b))

#論理積(AND)
print(bin(a & b))

#論理和(OR)
print(bin(a | b))

#排他的論理和(XOR)
print(bin(a ^ b))

#左シフト
print(bin(a << 1))

#右シフト
print(bin(b >> 2))

```

#####出力
```
-0b10011 -0b11010
0b10000
0b11011
0b1011
0b100100
0b110
```
出力は0bを除いてみれば，正しく演算されていることが分かる．

##感想
pythonでビット演算はしたことがなかったので，ビット演算の扱い方が知れたことはよかった．
また，今まで整数変換でしか使っていなかったintが基数変換に使えること，ほかにもbinという関数を知ることもできた．基数変換自体の仕組みについては今までも知っていたが，ここで改めて再確認するよい機会であったと思う．

##参考文献
Pythonで始めるアルゴリズム入門　伝統的なアルゴリズムで学ぶ定石と計算量
　　　　　　　　　　　　　　　　　　　　　　　　 増井 敏克　著　　翔泳社
【Ruby】any?メソッドの使い方

個人メモです。

any?メソッドを使うことで、**対象のオブジェクトの中に該当する要素が一つでもあればtrueを返す**。

・`オブジェクト.any?{ |変数|　条件式 }`


<br>
**ブロック`{}`を省略した場合は、対象のオブジェクトの中に値が存在すればtrueを返す**。

・`オブジェクト.any?`


<br>
##ブロックありの場合

**▼trueの事例**

```ruby:true1
arr = [1, 2, 3]

arr.any?{|x| x < 2}
=> true
```

**▼falseの事例**

```ruby:false1
arr = [1, 2, 3]

arr.any?{|x| x > 10}
=> false
```



<br>
##ブロックなしの場合

**▼trueの事例**

```ruby:true1
arr = [1, 2, 3]

arr.any?
=> true
```

```ruby:true2
arr = [nil, 2, nil]

arr.any?
=> true
```


<br>
**▼falseの事例**

```ruby:false1
arr3 = []

arr3.any?
=> false
```

```ruby:false2
arr4 = [nil, nil, nil]

arr4.any?
=> false
```
メソッド定義における基礎知識

# メソッドの定義

メソッドを定義するにあたっての基礎的な部分を
アウトプットを兼ねてこちらで共有していきます！！


###メソッドについて

そもそも、**メソッド**とはプログラミングにおいて何らかの処理をまとめたもののことを言い、そのメソッドの名称を記述することによって記述したメソッドの処理を実行することができます。

例えば、**lengthメソッド**を記述すれば文字列の文字数を出力することができます

※ターミナルのirbにて

```
irb(main):001:0> "baseball".length

=> 8
```


##メソッドの定義

###メソッド定義の記述
このようなメソッドは予め数多く存在していますが、すでにあるもののみならず自分で定義することで作成することができます。
メソッドを作成する際には以下のように記述します。

```
def メソッド名
  # 実行する処理のコード
end
```


これをもとに例文を作成してみると
例文↓

```
def my_hobby
  puts "私の趣味はプロ野球観戦です。"
end

my_hobby
# 出力結果
私の趣味はプロ野球観戦です。
```

上記のように、my_hobbyというメソッドを定義したことによって
my_hobbyと記述することによって「私の趣味はプロ野球観戦です。」を出力する処理を実行することができます！

コードが読まれる順番は普通では上からとなりますが、定義されたメソッドが存在する場合は、そのメソッドの記述は読まれずに一旦スルーされます。
上記の例で言うと、my_hobbyと記述してそれが読み込まれた段階で定義されたメソッドのmy_hobbyが呼び出されて処理が実行されます。


###実行したメソッドの最終的な値

メソッドを定義し、そのメソッドの処理が実行されて出力される値のことを**戻り値**または、**返り値**といい、上記の例文でいうと
**「私の趣味はプロ野球観戦です。」**という出力結果の部分が戻り値となります。

またlengthメソッドを用いた場合の戻り値は、文字数として出力された数字が戻り値となります。

そして定義されたメソッドに関しては、メソッド内の処理の1番最後の行の処理の結果が戻り値となって出力されます

例文↓

```
def week
  "Sunday"
  "Monday"
  "Tuesday"
  "Wednesday"
  "Thursday"
  "Friday"
  "Saturday"  # 1番最後の行が戻り値！
end

puts week
# => Saturday
```


このようにメソッド内の処理は最後の行が出力されるが
**return文**をメソッド内に記述すると戻り値を指定することができます！

例文↓

```
def week
  "Sunday"
  "Monday"

  return "Tuesday"  # これが戻り値となり、処理が終了する！

  "Wednesday"  # 呼び出されない
  "Thursday"  # 呼び出されない
  "Friday"  　# 呼び出されない
  "Saturday"  # 呼び出されない  
end

puts week
# => Tuesday
```

上記のようにreturnを指定することによって、戻り値として処理を行う部分を指定することができ、returnを記述した部分が出力されます。



###値の使用可能範囲

定義した変数を使用できる範囲は限られていて、その範囲のことを**スコープ**と言います。
`①定義したメソッド外で定義された変数をそのメソッド内で使用することは出来ず`、その逆も同じように`②定義したメソッド内の変数をメソッド外で使用することは出来ない`ためエラーとなります。

①の場合の例文↓

```
def introduce
  puts name
end

name = "Kinoshita"
introduce

# => エラー！
```



②の場合の例文↓

```
def introduce
  name = "Kinoshita"
end

puts name

# => エラー！
```

いずれも、スコープの範囲外ということで定義された変数が使えずにエラーとなってしまいます。
こういったスコープ範囲外で定義された値を使いには**引数（ひきすう）**という値を使用します。
引数を使用するには以下のように記述します。

例文↓

```
def メソッド名(仮引数)
  # 処理の記述
end

メソッド名(実引数)
```

**仮引数**はメソッドを定義する際に記述し処理の際に利用する引数で、
**実引数**はメソッドを呼ぶ際に受け取る値を記述する引数のことを言います。
また、引数は複数用いることができ、その場合は
`メソッド名（第1引数, 第2引数）`という記述をします。

仮引数と実引数の名称は必ずしも一致している必要はありませんが、引数の数は**必ず一致される必要があります。**

上記の例文のエラーを解決するために引数を用いてみます。
例文↓

```
def introduce(name)
  puts name
end

teacher = "Kinoshita"
introduce(teacher)

# => "Kinoshita"
```

上記のように、introduceメソッド外で定義されたteacherが実引数として記述することで、メソッド外で定義された変数teacherが、introduceメソッド内の仮引数nameとして渡され、メソッド内の処理を実行する。
これによってメソッド外で定義された変数が使用できる形になります！
javaScriptでwebpを使いたーい

##はじめに
iOS14/macOSビッグサーのsafariがwebpに対応したということで、そろそろwebpを使って行こうかと思ったのですが、なんとjsからwebp使用判定ができず。

いやjsで使いたいんだもん。jsアプリを作ってるんだし。
なんできないねん。

acceptヘッダ？ pictureタグ？
こんなこと言われてもね。

##対応できた
なんとか対応できました。

非表示のimgタグにbase64にした小さいwebpを埋め込んで、エラーハンドリングして確認。
scriptタグはその下へ移動。

```html
    <div style="visibility: hidden;">
        <img src="data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEACkC4JaQAA3AA/uZQAAA=" width="1" height="1"
            alt="" onload="webP=true;console.log('webp OK');" onerror="webP=false;console.log('webp NG');">
    </div>
    <script defer src="xxx.js"></script>
```
こうだね。
結構タイミングが狂うので、onloadも取ってチェックした方がいい。
iOS12とかのonerrorは結構タイミングが遅い。iOS14のonloadは割と早いけど、jsがキャッシュされてると、そっちの方が早かったりする。onloadのみでいいってことになる。

今回も手抜きな感じ:relaxed:
webサーバーとプロキシサーバーについて調べる (メモ)


##webサーバーとは
サーバーは
クライアントからの指示を受け取り、その内容に応じた情報を送り返す

**ブラウザが見に行っているWebに関するサービスを提供していサーバー**が
「Webサーバー」となる

サーバーは、**仮想的には1台**だけのマシンとして見えるが
実際は**複数のサーバーの集合体**である。
負荷を分散したり、他のコンピューター(キャッシュ、DBサーバー等)に
問い合わせを行う複雑なリクエストに応じて
全面的または部分的に文書を生成している

HTTP/1.1 と Host ヘッダーによって、**同じIPアドレス**を共有することができる

###主に使用されているプログラム
・**Apache**…デファクトスタンダードと言われるWebサーバー
一般的なLinuxディストリビューションの標準Webサーバーとして配布されている

・**Nginx**…Apache同様オープンソースなWebサーバーのひとつ

##プロキシサーバーとは…
「プロキシ」とは、「代理」という意味

**内部と外部のネットワークの中継をする役割を持つサーバー**で、
情報の受け渡しを行なう

なのでネットワーク内におけるインターネットの出入り口を、
プロキシサーバー経由に`限定`することで、
**通信内容を一括してプロキシサーバー側でチェック**することが可能となる

クライアントは直接インターネットにつながることがなく、
**不正アクセスや侵入行為を防ぐ**ことができセキュリティ向上目的で用いれる

ブラウザとウェブサーバーの間では、
多数のコンピューターや端末がHTTPメッセージを中継する

**アプリケーション層で行われる処理**は、通常プロキシと呼ばれる。

###使用される機能
・**キャッシュ**(キャッシュは共用、あるいは個人用にできる)
・**フィルタリング**(アンチウィルススキャンやペアレンタルコントロールなど)
・**負荷分散**(複数のサーバーが別々のリクエストに対応できるようにする)
・**認証**(さまざまなリソースへのアクセスを制御する)
・**ログ記録**(履歴情報の保管を可能にする)
・**匿名性の確保**(端末のIPアドレスがわからなくなる)

##参考記事
https://developer.mozilla.org/ja/docs/Web/HTTP/Overview
https://eng-entrance.com/web-server-mechanism
https://cybersecurity-jp.com/security-measures/32171
https://www.idcf.jp/words/proxy-server.html
非エンジニア向けに簡易的なアニメーションビューア作ってみた

株式会社グレンジでUnityエンジニアをしている @s_ebata と申します。
この記事は[グレンジ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/grenge)の12/17の記事です。

# はじめに

タイトルの通りですが非エンジニア向けに超絶簡易的なアニメーションビューア機能を作ってみました。
本来ならUnityのAnimatorウィンドウとAnimationウィンドウを使えば事足りる機能ですが、本機能は以下の点を重視して手早く作ったものになります。ご留意ください。

- 非エンジニア向け
- インスペクタで完結する
- アニメーションの指定と再生・停止ができる

## 環境
Unity 2018.4.27f1

# demo

こんな感じでLayersとStateをプルダウンから選択して再生・一時停止・再開・停止が可能です
![画面収録 2020-12-14 10.46.30.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218179/d3a4e3c8-0a55-f12e-d8dc-0e9ff2436712.gif)
Unityちゃんのアニメーションチェックシーン使っているため若干ややこしい見た目になってますが、インスペクタ内からアニメーションの指定と再生・停止・一時停止・再開ができているのが確認出来るかと思います。
解像度が低くて分かりづらいかもですが、ボタンは左からPlay、Pause、Resume、Stopとなっています。

動画には入っていませんが、AnimationEventsの設定有無も確認できます。

# 実装

難しいことは一切やっていません。ただただAnimator側の情報を取って表示しているだけです。
細かい制御などは端折って記載しています。

```csharp
// ...省略...

/// <summary>
/// CustomAnimator参照
/// </summary>
private CustomAnimator _customAnimator;

/// <summary>
/// レイヤー名を格納する配列
/// </summary>
private string[] _layerNames = new string[] { };

/// <summary>
/// ステート名を格納するディクショナリ
/// </summary>
private Dictionary<int, string[]> _stateNamesDict = new Dictionary<int, string[]>();

private int _layerIndex;

private CustomAnimator CustomAnimator
{
    get
    {
        if (_customAnimator == null)
            _customAnimator = target as CustomAnimator;
        return _customAnimator;
    }
}

public override void OnInspectorGUI()
{
    // ...省略...
    
    EditorGUILayout.LabelField("デバッグ再生");
    _layerIndex = EditorGUILayout.Popup("Layers", _layerIndex, _layerNames);

    var stateNames = _stateNamesDict.ContainsKey(_layerIndex) ? _stateNamesDict[_layerIndex] : new string[] { };
    _stateIndex = EditorGUILayout.Popup("States", _stateIndex, stateNames);
    _stateName = stateNames.Length > 0 ? stateNames[_stateIndex] : string.Empty;
    
    using (new EditorGUILayout.HorizontalScope())
    {
        if (GUILayout.Button("Play"))
        {
            var fullPathHash = Animator.StringToHash(string.Join(".", _animator.GetLayerName(_layerIndex), _stateName));
            CustomAnimator.Play(fullPathHash, _layerIndex, _normalizedTime, () =>
            {
                Debug.Log("Complete");
            });
        }
        if (GUILayout.Button("Pause"))
        {
            CustomAnimator.Pause();
        }
        if (GUILayout.Button("Resume"))
        {
            CustomAnimator.Resume();
        }
        if (GUILayout.Button("Stop"))
        {
            CustomAnimator.Stop();
        }
    }

    // ...省略...
}

// ...省略...
```

実行時にAnimatorControllerのLayersとStatesの拾い方がわからなくてググりました。
以下方法で拾えることがわかって勉強になりました。

```csharp
// UnityEditorのAnimatorControllerでキャスト
var controller = _animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
for (var i = 0; i < controller.layers.Length; i++)
{
    var layer = controller.layers[i];
    Debug.Log(layer.name); // レイヤー名

    var states = layer.stateMachine.states;
    foreach (var state in states)
    {
        Debug.Log(state.state.name); // ステート名
    }
}             
```

以上になります。
１−１．WEB系エンジニアになるためのインプット（準備）

#はじめに
メーカ系SIer企業で働いているのですが、少し物足りなさを感じております。
そこで副業の一環として、まずはWEB系エンジニアを目指すために「[web系エンジニアになろう](https://www.amazon.co.jp/21%E4%B8%96%E7%B4%80%E6%9C%80%E5%BC%B7%E3%81%AE%E8%81%B7%E6%A5%AD-Web%E7%B3%BB%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AB%E3%81%AA%E3%82%8D%E3%81%86-AI-DX%E6%99%82%E4%BB%A3%E3%82%92%E7%94%9F%E3%81%8D%E6%8A%9C%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%AA%E3%82%A2%E3%82%AC%E3%82%A4%E3%83%89%E3%83%96%E3%83%83%E3%82%AF-%E5%8B%9D%E5%8F%88/dp/4408339334)」（著：勝又健太）を読了しました。
まずは基礎を固めるためにインプットを行うが、併せて内容をアウトプットするために本記事を作成していく。

#学習フロー
既にコンピュータサイエンスの基礎知識やクラウドサービスであるAWSの知見を有しているので、下記のように進める。

1. Linux基礎
2. JavaScript基礎
3. RDBとSQL基礎
4. GitとGitHub基礎
5. Ruby基礎
6. Ruby on Rails基礎

以降はポートフォリオ作成を進めたい。

#教材
基本的には勤め先で提供されている**Udemy for business**を活用する。
※勤め先には感謝です・・・

例えば、Linux基礎では下記教材で学びを進めていく。
[【5日でできる】はじめての Linux 入門（LPIC Level1対応）](https://www.udemy.com/course/5dayslinux/)
（講師：井上 博樹 (Hiroki Inoue)）

#環境
PCはMacBookAirを利用している。

+ MacBook Air (Retina, 13-inch, 2019)
+ プロセッサー：1.6 GHz デュアルコアIntel Core i5
+ メモリ：8 GB 2133 MHz LPDDR3

また、Linux環境が必要である場合、VirtualBoxの利用も考えられるが、PC（Macを利用）が重たくなるので**AWSのEC2**を活用した。
例えば、Linux基礎で使う環境は下記とする。

+ リージョン：アジアパシフィック (東京)ap-northeast-1
+ AMI：Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
+ インスタンスタイプ：t2.micro

#最後に
まずはLinux基礎を固めるためにインプットを行い、次はLinux基礎のアウトプット記事を掲載する。
【Rails】デバッグ用gem 'better_errors' , 'binding_of_caller' を導入

# はじめに
ポートフォリオ作成で一番苦しんだのが、デバッグ！
そこで今回は、便利で高機能なエラー画面が表示されるらしい` better_errors`と` binding_of_caller`を導入してみました。

# 前提
- Ruby2.7.0
- Ruby on Rails6.0.3
- MySQL8.0

# ` better_errors`とは
デフォルトのエラー画面をわかりやすく整形してくれるgem。

# ` binding_of_caller`とは
上記` better_errors`と一緒に使うことで、ブラウザ上でirbを使えるようになるgem。

# いざ、導入
```ruby:Gemfile
group :development do
  gem 'better_errors'
  gem 'binding_of_caller'
end
```

```ruby:ターミナル 
bundle
```

※Dockerを使用している場合はもうひと手間必要とのこと。

```ruby:app/config/environments/development.rb
BetterErrors::Middleware.allow_ip! "0.0.0.0/0"
```

# エラー箇所の画面確認
下記のように、エラーメッセージやデバッグ画面が表示され、
ターミナルを表示しなくてもブラウザからのirbでデバッグ可能。
その他、トレース情報やリクエスト情報、ローカル変数なども確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905803/f9fe0f7d-94ce-5c0c-0d00-9a1bc75855f6.png)

# 終わりに
これはめちゃくちゃ便利！デバッグが捗る！
railsでアプリを作る際は、必ず導入しようと思います！

# 参考サイト
- [プログラミング初心者歓迎！「エラーが出ました。どうすればいいですか？」から卒業するための基本と極意（解説動画付き）](https://qiita.com/jnchito/items/056325421b7e36f02335)
- [Rails Better Errorsでデバックする (Ajaxでのエラーも)](https://qiita.com/shizuma/items/922eea72165c67a4a6e8)
- [Ruby / Ruby on Rails デバッグ方法まとめ](https://qiita.com/TakeshiFukushima/items/4e4cf281a3c7495f91e4) 
- [【Rails】もっと早く知りたかったデバッグ用gem 'better_errors','binding_of_caller'](https://qiita.com/terufumi1122/items/a6f9a939dce25b2d9a3e?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items)
- [Railsのデバッグが捗るエラー画面Better Errors使ってみた！](https://morizyun.github.io/blog/better-error-gem-rails-ruby-rack/index.html)
赤磐市防災協定締結

先日１２月１１日に岡山県赤磐市と防災協定を締結いたしました！
赤磐市とNPO法人クライシスマッパーズジャパンとの災害時に周辺状況を撮影し、市民の皆様へ提供するという活動を円滑に進める為の協定となっております。

発災時は、ボランティアを含めて、様々な救援部隊がドローンに限らず、現地入りして活動を行うわけですが、この協定があることによって、より活動しやすくなる、つまり、早く情報伝達が可能となるということになります。（かなりざっくりですが）

![IMG_9703.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322439/2622aca1-0a85-c40c-670b-85c2fb45a12f.jpeg)

これは、ゴールではなく、良いことの始まりです。
今後防災訓練なども含めて、地域とともに防災意識を高めていきたいと思います！
【Ruby】eachメソッドとfor文の違い。要素を一つづつ取り出し処理を行う。

個人メモです。

eachメソッドを使用すると、配列やオブジェクトなどの要素を一つづつ抜き出して、その値を使った処理を行うことができる。


##目次

1. [eachメソッドとfor文の違い](#eachメソッドとfor文の違い)
2. [eachメソッドの構文](#eachメソッドの構文)
3. [対象がrangeオブジェクトの場合](#対象がrangeオブジェクトの場合)
4. [対象が配列の場合](#対象が配列の場合)
5. [対象がハッシュの場合](#対象がハッシュの場合)
    6. [引数が１つの場合](#引数が１つの場合)
    7. [引数が２つの場合](#引数が２つの場合)
8. [each_pair, each_key, each_valueメソッド](#each_pair-each_key-each_valueメソッド)
    9. [each_pairメソッド](#1-each_pairメソッド)
    10. [each_keyメソッド](#2-each_keyメソッド)
    11. [each_valueメソッド](#3-each_valueメソッド)




<br>
##eachメソッドとfor文の違い
処理の内容はfor文と同じ。for文との違いは**変数のスコープ**。

<br>
**▼スコープの違い**
**変数が処理の中のみ有効か、外でも有効かの違い**となる。

- for文：　外でも有効
- eachメソッド：　中のみ有効。外では無効。

綺麗に処理を書きたければeachメソッドがベター。デメリットは変数を外と切り分けるため、処理量は若干大きくなる。（ほぼ気にする必要はない）


<br>
**▼対象がrangeオブジェクトの場合**
オブジェクトにrangeオブジェクト`..`や`...`を指定する場合は、eachはカッコで囲む必要がある（後述）。


<br>
##eachメソッドの構文

・`オブジェクト.each {|変数| 処理}`
　┗　オブジェクトはイテラブル
　┗　変数には取り出した一つ一つの値が入る
　┗　`{ }`を**ブロック**という


ブロック`{}`　は `do |変数| 処理 end`と同じ。

非破壊なので元のオブジェクトは変わらない。
また、他の変数に代入しても、元のオブジェクトと同じものになる。

```ruby:
range1 = 1..3
range2 = (1..3).each{|x| y = x*2;  p y }
#2
#4
#6

p range1   #1..3
p range2   #1..3
```



<br>
##対象がrangeオブジェクトの場合
対象がrangeオブジェクトの場合はカッコで囲む。

```ruby:
(1..3).each{|x| p x}

##出力
1
2
3
```

rangeオブジェクトはドットが２つの場合は終わりの値を含む。３つの場合は含まない。


<br>
**▼エラー**
カッコで囲まないとエラーになる。

```ruby:
1..3.each{|x| p x}
NoMethodError (undefined method `each' for 3:Integer)
```



<br>
**▼変数に代入**
rangeオブジェクトを代入した変数ならそのまま指定できる。

```ruby:
range1 = 1..3
range1.each{|x| p x}

##出力
1
2
3
```



<br>
**▼for文の場合**
for文の場合はカッコを付けなくても機能する。

```ruby:
for x in 1..3
  p x
end

##出力
1
2
3
```


<br>
##対象が配列の場合

```ruby:
arr = [1, 2, 3]
arr.each{|x| p x}

##出力
1
2
3
```

もちろん、処理後もarrは元のまま。



<br>
##対象がハッシュの場合
ハッシュの場合は指定する変数の数により取得できる要素が異なる。

| 変数の数 | 内容 |　取得要素の例 |
|:-:|:--|:-:|
| 1 |  キーと値  | [:a, 1] |
| 2 |  第1引数：キー、　第2引数：値、  | :a, 1 |


<br>
###引数が１つの場合
引数が１つの場合は、キーと値がセットになった配列を一つづつ取得する。

```ruby:引数が１つの場合
obj = {:a=>1, :b=>2, :c=>3}
obj.each{|x| p x}

##出力
[:a, 1]
[:b, 2]
[:c, 3]
```

<br>
###引数が２つの場合
引数が2つの場合は、第1引数がキー、第2引数が値となる。

**▼キーのみ出力**

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.each{|x, y| p x}

#出力
:a
:b
:c
```

**▼値のみ出力**

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.each{|x, y| p y}

#出力
1
2
3
```



<br>
##each_pair, each_key, each_valueメソッド
ハッシュのキーと値を取得する方法には、eachメソッドの変数で指定する意外に、各メソッドが用意されている。


###(1) each_pairメソッド
eachのブロックで変数を１つ指定したものと同じ。キーと値をセットの配列として取り出す。

```ruby:引数が１つの場合
obj = {:a=>1, :b=>2, :c=>3}
obj.each_pair{|x| p x}

##出力
[:a, 1]
[:b, 2]
[:c, 3]
```


###(2) each_keyメソッド
keyのみ取り出すメソッド

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.each_key{|x| p x}

#出力
:a
:b
:c
```


###(3) each_valueメソッド
値のみ取り出すメソッド

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.each_value{|x| p x}

#出力
1
2
3
```

<br>
eachメソッドの変数の数や指定方法で出しわければいいので、特にeach_xxxメソッドは使う必要がなさそう。
【ズボラ】簡単にS3署名付きURLを発行したい【手抜き】

# 経緯
？「非公開S3バケットのデータを期間限定で公開したい」
俺「aws-cli叩いてpresign発行したら？」
？「コマンド叩きたくないでござる」
俺「・・・あ！マネコンから開いたら５分限定で見れたはず！」
？「ネ申！」
俺「・・コマンド叩いたら良いのに」

という流れがあったので、S3署名付きURL発行の手抜き版です。

# 前提
+ すでにS3バケットは非公開で作成済み
+ S3触れるIAMアカウントでデータも保存されている
+ そのアカウントの持ち主はコマンド嫌い

## 手順①：メニューから開く
S3のマネジメントコンソールにて当該ファイルを選んで、アクションメニューから「開く」を選択
![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798/40892bc3-49f6-4612-7dcf-3f6dc31e33ac.png)

## 手順②：見れた！
ファイルがもちろん開きますよね？
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798/a17d866e-581a-04c1-463d-d9daa068fe22.png)

## 手順③：URL共有
この閲覧時のURLが実は５分限定で見れるという。。
![04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798/501711fa-1a96-6b3a-6473-a1e9a3f31c71.png)
（めちゃくちゃURL長い・・・汗）

# aws cliで設定する場合
コンソールでコマンド叩いて設定するならaws cliなら以下のように叩きます。

```bash
aws s3 presign --exipres-in 秒数 s3://バケット名/データ名

例) ウルトラマンのように3分間戦うなら！
aws s3 presign --expires-in 180 s3://handson-bucketname-origin/test.txt
　↓
https://handson-bucketname-origin.s3.amazonaws.com/test.txt?AWSAccessKeyId=xxxxxxxxxx&Signature=xxxxxxxxxxxxxxxxxxx%3D&Expires=16080xxxxx
```
>一部マスクしてます。

# 備考
AWS CloudShellが2020/12/16に発表されましたが、そこならaws cli入っているので環境準備も楽だと思います。
![05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798/f30637a9-64bb-a847-6ec8-b95e00e07982.png)


# 参考
[AWS CLI コマンドリファレンス](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/presign.html)
[【小ネタ】AWS CLIでS3のPre-Signed URLを生成できるようになっていました！](https://dev.classmethod.jp/articles/generate-s3-pre-signed-url-by-aws-cli/)
Java　HTMLをPDFで保存

<p>HTMLをPDFで保存するには、様々な方法がありますが、試しにネット上で検索をかけたところ、複雑でしょうがないでしょう。</p>
<p>さあ、本文ではSpire.Doc for Javaを通してHTML StringとHTML ファイルというHTML形式をPDFで保存する方法を紹介します。</p>
<h4>下準備</h4>
<p>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/doc-for-java-free.html">Free Spire.doc for Java</a>無料版をダウンロードしてください。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201216/20201216121839.png" alt="f:id:lendoris:20201216121839p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.doc.jarを参照に追加してください。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201216/20201216121952.png" alt="f:id:lendoris:20201216121952p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>HTML String </strong><strong>を</strong><strong>PDF</strong><strong>で保存</strong></p>
```JAVA
import com.spire.doc.*;
import java.io.*;

public class htmlStringToWord {

    public static void main(String[] args) throws Exception {

        String inputHtml = "InputHtml.txt";
        //documentを作成します。
        Document document = new Document();
        // sectionを追加します。
        Section sec = document.addSection();

        String htmlText = readTextFromFile(inputHtml);
        //段落とhtml stringを追加します。
        sec.addParagraph().appendHTML(htmlText);

        // PDFで保存します。
        document.saveToFile("HTMLstringToPDF.pdf", FileFormat.PDF);
    }
    public static String readTextFromFile(String fileName) throws IOException{
        StringBuffer sb = new StringBuffer();
        BufferedReader br = new BufferedReader(new FileReader(fileName));
        String content = null;
        while ((content = br.readLine()) != null) {
            sb.append(content);
        }
        return sb.toString();
    }
}
```

<h4>HTML ファイルをPDFで保存</h4>
```JAVA
import com.spire.doc.*;
import com.spire.doc.documents.XHTMLValidationType;

public class htmlFileToWord {

    public static void main(String[] args) throws Exception {
        //  HTML ファイルをロードします。
        Document document = new Document();
        document.loadFromFile("InputHtmlFile.html", FileFormat.Html, XHTMLValidationType.None);

        //保存します。
        document.saveToFile("Result.pdf",FileFormat.PDF);
    }
}
```
<p> </p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201216/20201216123643.png" alt="f:id:lendoris:20201216123643p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
Apple Silicon MacでGHC masterをビルドするメモ

この記事は元々arm64-apple-darwin向けの公式バイナリーが出る前に書かれたが、2021年8月現在の状況を反映して大幅に書き換えられた。古い話（Rosetta 2を使ったbootstrappingとか）に興味のある人は記事の編集履歴を見てほしい。

# 公式のissue

これが公式のissueだったが最近は更新されていない：

* [Support for Apple ARM hardware (#18664) · Issues · Glasgow Haskell Compiler / GHC · GitLab](https://gitlab.haskell.org/ghc/ghc/-/issues/18664)

メモ：

* 言及されているghc.nixはこれ：[alpmestan/ghc.nix: Nix (shell) expression for working on GHC](https://github.com/alpmestan/ghc.nix)
    * `configure_ghc` というのはghc.nixが提供するシェル関数っぽい
* [このコメント](https://gitlab.haskell.org/ghc/ghc/-/issues/18664#note_318440)の「Apple's R^X requirement」はメモリーの read-xor-execute のことっぽい？（Appleそんなことやってんのか）

すでにApple Silicon対応のバイナリー（8.10.5以降）がリリースされ、masterブランチにAArch64 NCGも入ってしまった今となってはこのissueもほぼ用済みかもしれない。あとはGHC 9.0.2が出れば……。

# 必要な外部のツール類

## python3, automake, autoconf, llvm-11

筆者はMacPortsで入れた。

```shell-session
$ port install python3 automake autoconf cmake llvm-11
```

これで `opt-mp-11` コマンドと `llc-mp-11` コマンドが使えるようになるはず。

## Haskell環境のインストール

[Apple Silicon MacにGHC/cabalを入れるメモ - Qiita](https://qiita.com/mod_poppo/items/894e3b43febb3a909eed)にも書いたが、ghcupやstackが対応していない現段階ではHomebrewで入れるのが手っ取り早い。

```shell-session
$ brew install ghc cabal-install
```

GHCをビルドするための `alex` と `happy` を入れる。

```shell-session
$ cabal install alex happy
```

ghc-9.0 をビルドする際には happy 1.19.x が必要なようなのでバージョンを指定する。

```shell-session
$ cabal install --constraint="happy==1.19.*" --overwrite-policy=always happy
```

# GHCのビルド

まず、GHCを「x86_64で動作し、AArch64バイナリーを吐く」クロスコンパイラーとしてビルドする。

```shell-session
$ git clone --recursive https://gitlab.haskell.org/ghc/ghc.git
$ cd ghc
$ ./boot
$ ./configure --with-intree-gmp LLC=llc-mp-11 OPT=opt-mp-11 ALEX=$HOME/.cabal/bin/alex HAPPY=$HOME/.cabal/bin/happy
$ hadrian/build --flavour=quick -j
```

これで `_build/stage1/bin/ghc` （あるいはエイリアスとして `_build/ghc-stage1`）ができる。

masterブランチ（あるいは9.2ブランチ）にはAArch64 NCGが入っているので、LLVMがなくても動作するはずだ。LLVMバックエンドを使いたい場合は `-fllvm` を指定すれば良いし明示的にNCGを指定したい場合は `-fasm` を指定すれば良い。
pictureタグを使ってWebPをレスポンシブ対応させる

#はじめに
WebPはGoogleが開発した画像フォーマットです。
圧縮率の高い非可逆圧縮で、透過した画像も書き出せ、GIF同様にアニメーションにも対応しています。
今回は`<picture>`を使って手軽にレスポンシブ対応させる方法をご紹介します。

#完成形はこんな感じ

<p class="codepen" data-height="400" data-theme-id="dark" data-default-tab="html,result" data-user="iwahashi_a" data-slug-hash="GRqxWgb" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="WebPをpictureタグでレスポンシブ">
  <span>See the Pen <a href="https://codepen.io/iwahashi_a/pen/GRqxWgb">
  WebPをpictureタグでレスポンシブ</a> by Iwahashi Aki (<a href="https://codepen.io/iwahashi_a">@iwahashi_a</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

#用意するもの

+ WebP画像（pc.webp、sp.webp）
+ WebP非対応ブラウザ用の画像（pc.jpg、sp.jpg）
+ Picturefill.js
    + `<picture>`はIE11非対応なのでポリフィルを使いましょう！
    + http://scottjehl.github.io/picturefill/

#pictureタグの使い方
`<picture>`を使うことで、画像を出し分けることができます。
例えば以下のように記述すると、700px以上のときにはpc.jpgを表示し、700px未満のときにはsp.jpgを表示することができます。

```html:html
<picture>
  <source srcset="pc.jpg" media="(min-width:700px)" />
  <img src="sp.jpg" alt="sp.jpg" />
</picture>
```
`<picture>`の中には0個以上の`<source>`と、1つの`<img>`を入れます。
`<source>`はいくつ使用してもOKですが、`<img>`より前に記述してください。

##IE11への対応
`<picture>`はIE11非対応です。そこでPicturefill.jsというポリフィルを使いましょう。

Picturefill.js
http://scottjehl.github.io/picturefill/

#WebPの使い方
WebPを表示させるときにも`<picture>`を使います。
WebPはまだ対応していないブラウザがあるため、非対応ブラウザ用に画像を出し分ける必要があるからです。

対応ブラウザ: Chrome, Edge, Firefox, Opera, Safari（iOS14）

以下のように記述すると、WebP対応のブラウザではpc.webpを表示し、WebP非対応のブラウザではpc.jpgが表示されます。

```html:html
<picture>
  <source srcset="pc.webp" type="image/webp" />
  <img src="pc.jpg" alt="pc.jpg" />
</picture>
```

#2つを合体！完成！
上記の2つのコードを組み合わせてWebpをレスポンシブ対応させます。

```html:html
<picture>
  <source srcset="pc.webp" media="(min-width:700px)" type="image/webp" />
  <source srcset="pc.jpg" media="(min-width:700px)" />
  <source srcset="sp.webp" type="image/webp" />
  <img src="sp.jpg" alt="sp.jpg" />
</picture>
```
行なっている処理の内容は以下になります。

1. ブラウザ幅700px以上で、WebP対応ブラウザならpc.webpを表示
2. ブラウザ幅700px以上で、pc.jpgを表示
3. ブラウザ幅700px未満で、WebP対応ブラウザならsp.webpを表示
4. 上記のどれにも当てはまらなかったら、sp.jpgを表示

`<picture>`は上から順番に条件判定をしてマッチしたものがあれば、その後の条件は無視されます。
もし1と2を逆に記述した場合、pc.webpが表示されることは永遠にないので記述する順番にはくれぐれもご注意ください。

#おわりに
WebP非対応ブラウザへの出し分けがあるため、少しコードの量が多くなってしまいます。
サーバーサイドで出し分ける方法もありますが、部分的に使用したいという際にはこの方法が1番手軽かと思います。
WebPが全てのブラウザに対応する日が楽しみです。

#参考文献
_次世代画像形式のWebP、そしてAVIFへ –変わり続ける技術に対応するweb制作の黄金解–_
https://ics.media/entry/201001/

_picture: 画像要素_
https://developer.mozilla.org/ja/docs/Web/HTML/Element/picture

_画像ファイルの種類と形式ガイド_
https://developer.mozilla.org/ja/docs/Web/Media/Formats/Image_types
Eclipseデバッグ起動時に`ERROR: JDWP Transport dt_socket failed`エラーが出て起動できない


以下のようなエラーがコンソールに出力されて起動できなくなる  

```
ERROR: transport error 202: handshake failed - connection prematurally closed
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [./open/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c:734]
```

原因はいろいろあるようだが、自分の場合は`ESET`というウィルス対策ソフトのファイヤーウォールが原因。  

ESET上に許可するルールを追加してあげたら起動できるようになった。
自分の場合は内向きの一定のポート範囲（50000-65000）を許可してあげた。
（ルールの追加は自己責任でお願いします！）
Blenderで3Dモデルを作ってUnityで表示してみた

# はじめに

こんばんは。ごだと申します。
今回はゲームでは欠かせない3Dモデルがどのように作られるのか前より気になっていたので調べてみました。
実際に3Dモデルを作成し、それをUnityでアセットとして利用してみたいと思います。
今回はこのような傘を題材にしていきます。

# モデリング

まずは3Dモデルの格子となるメッシュを作成していきます。
今回は記事名の通り、Blenderを使用して以下のようなモデルデータを作成しました。
このデータを作るにあたり、気づいたことを記載します。
![2020-12-15_14h17_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/2c808e1e-36f8-04d3-1b42-6db61a8d273d.png)

## モディファイア

モデリングは基本的に立方体などプリミティブな形状に変形や分割といった操作を加えることで形状を作っていくものと思っていましたが、実際には`モディファイア`という機械的に形状を作る機能があり、楽することができました。

### ミラー
メッシュを左右対称にする機能です。これを使えば実際に作り込むのは1/2で済みます。
![2020-12-16_16h44_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/beba031f-a6ab-382a-07bc-d4a92bd08f5d.png)

### 配列
メッシュを複製し、等間隔で並べる機能です。
![2020-12-16_16h45_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/22822c2a-a094-8713-4c41-66c18c75f3a6.png)

### サブディビジョンサーフェス
メッシュを規則的に分割し、複雑な曲面を作れる機能です。
![2020-12-16_16h51_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/470d6498-68a4-82c6-bc71-13392d84e538.png)

## 四角形ポリゴン

モデリングは四角形でポリゴンで作ることが良しとされているようです。
五角形や六角形などの多角形ポリゴン、三角形ポリゴンはレンダリングソフトによっては正しく描画されないことがあるようです。
![2020-12-15_23h43_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/0574ecc6-6ae3-253d-0b89-66ba6723d4c2.png)

## 面の向き

ポリゴンには表と裏があり、夢中で作っていると面の向きがごちゃごちゃになっていってしまいます。CGで基本的には裏面は表示されないため、外側にくるところは表面に直す必要があります。

Blenderには表裏を区別して表示する機能があるため、それを使うことで状態を確認することができます。
![2020-12-15_20h47_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/0ce62b7e-b13f-bc98-0b19-9b3749448ecd.png)
青色が表面、赤色が裏面となるため、以下の操作ですべて表面に直します。
![2020-12-15_20h48_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/90be694d-1a3f-70e7-29f9-8e867a46f09d.png)

## UV展開

ポリゴンにUVを設定します。
Blenderではシーム（切れ込み）を入れて、3次元のモデルを2次元の画像に展開していきます。
![2020-12-16_11h04_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/4460f902-5a37-c0c6-c2bf-bfe287cd6324.png)


# テクスチャ作成

テクスチャの作成には`SubstancePainter`を使用します。
SubstancePainterは3Dペイントを行うソフトで、以下のようなレイアウトでモデルとUV展開図を見比べながらテクスチャを作成できます。書き込みは左右どちらのビューでも行うことができます。
![2020-12-15_22h34_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/f327e156-1d5d-036b-1832-b94fa8169fa8.png)
マスクで範囲を指定しつつ、ブラシやマテリアルを使って以下のように塗り分けていきます。
マスクはメッシュ単位で作成することができるのが便利です。
![2020-12-15_23h33_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/58d41baa-583a-ef0d-685f-d84406c86623.png)
Irayで好きなタイミングで見栄えの確認を行うことができるのも嬉しいです。
![2020-12-16_11h32_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/10e1a589-b3c0-98a2-2a24-a31a5051fa58.png)

# Unityで表示
これまでで作ったFbxとテクスチャをUnityに持ち込みます。
![2020-12-16_12h08_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227584/ed5caebe-3c0b-96e0-68ba-f696291cdaf9.png)
HTMLでクリスマスツリー

今回はhtmlのsvgタグを使ってクリスマスツリーを書いています
予め作成したsvgではなくpathで直接書いています

## ポイント
pathタグのd属性にsvgを書いていく
Mで開始点を指定してZで終わりです。
中に直線(L)や円弧(A)をつかって図形を書いていきます
他にもベジェ曲線なども使えます

## 成果物
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="html,result" data-user="yakipote" data-slug-hash="RwGpmMQ" style="height: 600px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="tree">
  <span>See the Pen <a href="https://codepen.io/yakipote/pen/RwGpmMQ">
  tree</a> by yakipote (<a href="https://codepen.io/yakipote">@yakipote</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
https://codepen.io/yakipote/pen/RwGpmMQ

## アニメーションも

過去に作ったものですがアニメーションも実装できます(マウスオーバーでで動きます)

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="html,result" data-user="yakipote" data-slug-hash="oYJKLG" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="sakura mouseover animation">
  <span>See the Pen <a href="https://codepen.io/yakipote/pen/oYJKLG">
  sakura mouseover animation</a> by yakipote (<a href="https://codepen.io/yakipote">@yakipote</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

## 参考
https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Paths
enum 文字列で保存する vs 数字で保存する



- 文字列の場合
  - メモリやディスク容量を使う。（わずかな違い）
  - バリデーションのパフォーマンスが悪い（わずかな違い）
  - 文字列だとenumに無い値が入ってしまう恐れがある。
  - DBデータを見ると他に何も参照することがなくどんな値が選択されたかがわかる。
- 数字の場合
  - メモリやディスク容量を使わない。（わずかな違い）
  - バリデーションのパフォーマンスが悪い（わずかな違い）
  - enumを変更すると数字とのずれが生じるリスクがある。
  - DBデータを見たときにどんな値が入っているかをソースコードを見て確認する必要がある。
【VScode】the remote host may not meet vs code server's prerequisites for glibc and libstdc++ vscode

VScodeでリモートサーバーにSSHで接続しようとしたら起きたエラー

なんかVScodeの右下に表示されたやつ

```
the remote host may not meet vs code server's prerequisites
 for glibc and libstdc++ vscode
```

意味わかんな。。
まぁ、リモートサーバーにアップデートかければ治りそうだな。

```
sudo yum update
```
アプデしよー
。。。

```
中略  Read-only file system
```

え？なんでいきなり_？ワイrootなんやが。

```
# mount -o rw,remount /
```

```
sudo yum update
```

はい接続できた！！
ngrokについて

#ngrokとは
ローカルWebサーバーをインターネットに公開出来るサービスです。
デプロイをしていなくとも ngrok を通して作ったサービスを公開できる。
（ デモサイトを試す時なんかに使えます ）
HTTP/HTTPS 通信だけではなくSSHでも外部から接続できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/836751/22ef3c80-d159-2598-7636-f30eaeaa31a3.png)
画像参考：　[ngrokの利用方法](https://qiita.com/hirokisoccer/items/7033c1bb9c85bf6789bd　)


##使い方
###①インストール

```
 brew install ngrok
```
上記でダメだった場合　`brew cask install ngrok`

###②起動

```
ngrok http 80
```
上記コマンドを入力すると

```
ngrok by @inconshreveable

Tunnel Status                 online
Version                       2.3.35
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://92832de0.ngrok.io -> localhost:80
Forwarding                    https://92832de0.ngrok.io -> localhost:80

Connnections                  ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```
と`UI`が表示され
Web Interface →　トンネルのパブリックURL
Forwarding 　→　トンネルを介して行われた接続に関するその他のステータス
このForwardingで表示されたURLにアクセスすればOKとなります。
 
SSL認証までをngrolが肩代わりしてくれていますので公開エンドポイントまでSSL通信が可能です。

すごく便利ですね:relaxed:


##参考


https://qiita.com/hirokisoccer/items/7033c1bb9c85bf6789bd
https://qiita.com/mininobu/items/b45dbc70faedf30f484e
simple_formのdateをカレンダーにする

メモ

https://notsobad-jp-blog.tumblr.com/post/72997552476/simpleform%E3%81%A7%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%A4%87%E9%9B%91%E3%81%AA%E3%81%93%E3%81%A8%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AE%E3%83%A1%E3%83%A2
データサイエンスⅠ メモ

# Week 1
## 1.5
### データ取得先
- e-Stat: 政府統計
- RESAS: 官民ビッグデータ
- 金融データ
- Kaggle
- Google Map（曜日・時間別の入場者数）
- スクレイピング
- SNS
[mooc1/getDataFromGMap\.py at master · kuni10saito/mooc1](https://github.com/kuni10saito/mooc1/blob/master/getDataFromGMap.py)

## 1.7 画像解析
画像解析でできること
- 人間の位置・動き・視線・人数・年齢・表情・感情
- 物体の位置・形・動き・数・物体カテゴリ・質感
- シーンの撮影場所・形状・照明条件・天候

- 指紋認識・顔認識・人数計測
- 測量・計測・景観シミュレーション
- 自動運転・安全運転支援
- 医用画像診断・生活支援・見守り・介護

## 1.8 画像処理の応用
研究テーマ決めに使えそう．
- 画像は3Dを2Dにしているため，情報が失われている
- 2枚の画像を使った三角測量，距離が分かる画像（奥行画像）
- 動き情報からの三次元復元．動画像から三次元的な情報を取り出せる
- 周囲からの写真から三次元モデルを作れる
- 画像合成：自由視点映像生成．遠隔ロボットの操縦
- 画像合成：画像修復
- 画像合成：移動物の自動消去
- 画像合成：リアルタイムでの物体消去

## 1.9 音声処理
業務に役立つかも

- 音声認識
- 話者認識
- 声紋認識
- 音声合成
- 騒音調査
- 探知・測距
- 音楽情報処理

### 音声データ形式
- パルス符号変調
- ヘッダーを付けたファイル .wav （サンプリング周波数など）
- 圧縮したファイル .mp3
- スペクトル：PCMデータ→一定時間のフレームに区切る→周波数成分に変換→周波数ごとの強さに変換→スペクトル
- スペクトル包絡：縞などの微細構造を無視した外形をスペクトル包絡と呼ぶ．スペクトルデータ→微細構造を落とすフィルタバンク→対数→スペクトル包絡
- フォルマント：スペクトル包絡のピーク．

## 1.10 音声認識
- 音素：発音記号のようなもの ex, a i u k s ch...
- 単語並び・音素並び　辞書と照らし合わせる
- 単語並びの確率（言語モデル）
- 時間伸縮マッチング：一つの音素は複数フレームにまたがる．隠れマルコフモデル（HMM）を用いる．


# Week2
## 2.2
- 第一四分位点：データを中央値で分割したとき，小さいグループの中央値

## 2.7
- 決定係数：回帰直線のデータへの当てはまりを表す指標．

## 2.8
- 因果関係があれば相関関係がある
- 相関関係があっても因果関係があるとは限らない

## 2.10
- 系統抽出：通し番号を付け，均等な間隔に標本を選ぶ
- クラスター抽出：いくつかのクラスターに分け，その中から一つを選び，全数調査．
- 層化抽出：男女比1:3
- 多段抽出：クラスター抽出を繰り返し，最後に選ばれたクラスターの中からランダムに標本を選ぶ．
CSVをアップロードしてデータベースに入れる（備忘録）

基本のやり方はコチラ
https://qiita.com/junara/items/183aaff5e5b77ec1c679#%E3%83%A2%E3%83%87%E3%83%AB

１、rails console を立ち上げる

２、Supporter.simple_import(path: 'db/test_mail_list.csv', col_sep: ',') 
　　↑こちらを入力
　　Supporterの部分は、必要に応じて変更。User、Eventなど。

３、Supporter.where(event_id 19).destroy_all
　　↑入力全部消すとき

４、test_mail_list.csvのファイルの場所は dbフォルダ直下

上記で簡単に操作できる。
yumコマンドが急に使えなくなった時の対処法

なんかいきなり「Read-only file system」とか言われるんやが？

なんで？なんで？なんで？なんで？なんで？なんで？なんで？なんで？なんで？なんで？

作業停止1-2時間

ワイは見つけた。

```
# mount -o rw,remount /
```
なんかこれで「Read-only file system」とか言われなくなった！！

linuxコマンド勉強しよーって思った。
【Ruby】rangeオブジェクトのドット2つとドット３つの違いについて。

個人メモです。

連続した数値を表すrangeオブジェクトの`..`と`...`の違いについて。

##違い
終わりの値を含むかどうか

| rangeオブジェクト | 終わりの値 |
|:-:|:-:|
| ..  | 含む  |
| ...  | 含まない  |


<br>
##ドット２つ
ドット２つの場合は終わりの値を含む。
`1..3`とすれば**3も含む**。


```ruby:
for i in 1..3
  p i
end

##出力
1
2
3
```


<br>
##ドット3つ
ドット3つの場合は終わりの値を含まない。
`1..3`とすれば**3を含まない**。


```ruby:
for i in 1...3
  p i
end

##出力
1
2
```
【Ruby】キーを指定して値を取得する方法。ハッシュ、シンボル、fetchの違い

個人メモです。

オブジェクトのキーを指定して値を取り出す方法には、ハッシュやシンボルでキーを指定する他に、fetchメソッドを使う方法も存在する。

```
・シンボル：　obj[:a]
・ハッシュ：  obj['a']   （ obj["a"]も同じ )
・fetch:    obj.fetch(:a)  または  obj.fetch('a')
```

##目次

1. [ハッシュ、シンボル、fetchの違い](#ハッシュシンボルfetchの違い)
    2. [①元のオブジェクトの形式による違い](#元のオブジェクトの形式による違い)
    3. [②存在しないキーでエラーを表示するか？](#存在しないキーでエラーを表示するか)
4. [fetchメソッド](#fetchメソッド)
    5. [例外処理１](#例外処理１)
    6. [例外処理２](#例外処理２)
    7. [例外処理１と例外処理２を２つとも記述した場合](#例外処理１と例外処理２を２つとも記述した場合)
 




<br>
##ハッシュ、シンボル、fetchの違い
それぞれの違いは、

- ①**元のオブジェクトの形式**が何か？
- ②存在しないキーで**エラーを表示**するか？

の２点になる。


<br>
##①元のオブジェクトの形式による違い

オブジェクトのキーの指定方法は**ハッシュ**と**シンボル**がある。

**ハッシュは文字列。シンボルは前方にコロン**がついた記述となる。値を取得するときの指定はそれぞれの形式に合わせる必要がある。


```ruby:ハッシュ形式の例
obj = {"a"=>1, "b"=>2, "c"=>3}

##値の取得
 obj2['b']
=> 2

##NG
obj[:b]
=> nil
```

<br>

```ruby:シンボル形式の例
obj = {:a=>1, :b=>2, :c=>3}

##値の取得
obj[:b]
=> 2

##NG
obj['b']
=> nil
```

つまり、`'b'` と `:b`はイコールではない。

ハッシュは定義したオブジェクト毎に固有だが、シンボルは同じキーであれば全て同一になるという違いがある。



<br>
##②存在しないキーで**エラーを表示**するか？
上記の例でわかるように、シンボルとハッシュを指定した場合、**指定したキーが存在しなくてもエラーにはならず、`nil`が返る。**

**エラーを表示したい場合にfetch**を使う。

```ruby:
obj = {:a=>1, :b=>2, :c=>3}

##値が存在する場合
obj.fetch(:b)
=> 2

##値が存在しない場合 case1
obj.fetch(:g)
KeyError (key not found: :g)

##値が存在しない場合 case2
obj.fetch("b")
KeyError (key not found: "b")
```

存在しない値を指定すると`KeyError (key not found: 指定したキー)`が返る。



<br>
##fetchメソッド
fetchメソッドでは第2引数やブロックを記述することで、エラー時の表示内容を指定することができる。（例外処理が簡単に指定できる）

・`オブジェクト.fetch(キー, 例外処理1){|変数2| 例外処理2
}`

- 例外処理１は変数でも、値でも指定可能
- 例外処理１と例外処理２が両方記載されている場合は 例外処理２が優先される
- 例外処理2の変数2にはキー名が入る
- `{}`内に`|変数|`の記述がないときは処理結果のみが返る。


<br>
###例外処理１

・`オブジェクト.fetch(キー, 例外処理)`

**▼文字列で指定**

```ruby:文字列で指定
obj = {:a=>1, :b=>2, :c=>3}
obj.fetch(:g, "errorです")

=> "errorです"
```

<br>
**▼変数で指定１**

```ruby:文字列で指定
obj = {:a=>1, :b=>2, :c=>3}

e = "errorです"
obj.fetch(:g, e)

=> "errorです"
```

<br>
**▼変数で指定２**
カッコの中で変数に値を代入することも可能。

```ruby:文字列で指定
obj = {:a=>1, :b=>2, :c=>3}
obj.fetch(:g, e = "errorです")

=> "errorです"
```


<br>
###例外処理２
・`オブジェクト.fetch(キー){|変数| 例外処理}`

ブロック`{}`で例外処理を指定することも可能。

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.fetch(:g){|x| "#{x}は存在しません"  }

=> "gは存在しません"
```

<br>
**▼変数展開**
文字列`""`の中で`#{変数}`を記述することで変数の値を文字列として表示できる。


<br>
**▼変数を指定しない場合**
変数を指定しない場合、例外処理の記述のみが返る。

```ruby:
obj = {:a=>1, :b=>2, :c=>3}
obj.fetch(:g){ "エラーです" }

=> "エラーです"
```


<br>
###例外処理１と例外処理２を２つとも記述した場合
例外処理１と例外処理２を２つとも記述した場合は、警告メッセージと共に、例外処理２が返る。

```ruby:
obj.fetch(:g, "error1です"){ "ERROR2です" }
warning: block supersedes default value argument
=> "ERROR2です"
```

supersedesは取って代わるの意味。
Paletteでのtox管理

この記事は[TouchDesigner Advent Calendar 2020](https://qiita.com/advent-calendar/2020/touchdesigner)の16日目の記事です。


COMPs内の複数のノードをまとめて.toxファイルとして管理/再利用できる機能は使ってる方も多いと思います。

toxの基本的な機能や解説は@ToyoshiMoriokaさんのこちらの記事が詳しいです。
[Containerを作る/Containerを使う](https://qiita.com/ToyoshiMorioka/items/4e6ba9981874f2d3975c)


toxファイルの管理の仕方としては
1. 外部のディレクトリに保存して(external)toxとして利用する
2. TouchDesigenrのPalette上で管理

の2種類があると思いますが個人の範囲では再利用を前提とした機能的なtoxはPalette上で管理することが多く、前者の方法は複数人で一つのプロジェクトを管理するときなどによく利用しています。

今回はPaletteでのtox管理やちょっとしたTIPsを紹介します。
## Paletteを開く
左上のOpen PaletteボタンからPaneとしてPaletteを表示することが多いと思いますが、`Alt + L` でfloating windowとして開くこともできます。
![out2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/8bf85c86-8c13-ef07-2052-116f62922ef1.gif)

PaletteのCOMPにはDerivative社があらかじめ用意してくれてるものとユーザーが自分で保存するものの2種類があります。デフォルトではいってるもののそれぞれの機能については@joe0haraさんがまとめてくれています。
[TouchDesigner Palette まとめ](https://note.com/joe0hara/m/m62e2978310e3)

##  COMPをPaletteに保存する
PaletteのMyComponets内で右クリ>Add Folderで作成したフォルダにドラッグアンドドロップすれば保存されます。保存されたものはネットワーク上にドラッグアンドドロップすることでいつでも呼び出すことができます。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/b8706968-c8cc-0482-f184-6ff9df7b96d7.gif)

Paletteで保存したCOMPは`C:\Users\ユーザー名\Documents\Derivative\Palette`にpaletteData.jsonというファイルと一緒にtoxとして保存されています。なのでPCを新調したとしてもこれらをコピーしてこの場所に保存すれば同様にPaletteからアクセスできます。


## text TOPでアイコンを表示
外部ファイルを参照したり、やることが複雑になってくるとPaletteでのtox管理はなかなか難しくなってきますが、UI用の簡素な画像ファイルとかであればTouchDesigner内の機能で代替可能です。

真っ先に思いつくのはLockフラグで画像ファイルのcookとアップデートを走らないようにするという方法ですが、text TOPからMaterial Design Iconsを利用するという手もあります。
![スクリーンショット 2020-12-15 201629.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/5628477c-7858-fb2d-d59a-b30cacfa7321.png)
text TOPのfontをMaterial Design Iconsに指定して、[こちらのチートシート](https://cdn.materialdesignicons.com/4.7.95/)を参考にしながらtextのpython expressionで `chr(0x該当コード)` を入力すると指定したアイコンが表示されます。

※少なくとも執筆時点では最新のMaterial Design IconsのバージョンとTouchDesignerは対応していません。少し古いバージョン(v4.7.95)である上記のチートシートを参考にしてください。

## Palette上でtoxのサムネイルとテキストを表示する
COMP内にLockフラグをオンにしたiconという名前のTOPを配置/helpという名前のDATを配置するとPaletteに保存したときに左下のiconタブでアイコン、Infoタブでテキストを表示することができます。
![スクリーンショット 2020-12-15 224837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/ff0413f3-c878-7604-74e0-157c031b64d9.png)
![スクリーンショット 2020-12-15 224502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/b211e8db-36e1-34ba-278b-b7fbc9a10ff6.png)　![スクリーンショット 2020-12-15 224521.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529920/6a7419d2-802a-4f41-66b9-147d4f8ac946.png)
（我が家のPC運用）ダッシュボードで運用情報を確認

# 我が家の運用情報の確認
[前回](https://qiita.com/suwanishi77/items/ac12405b57311928cd07)、[前々回](https://qiita.com/suwanishi77/items/b8c0c5f1fce1b29949df)とWindowsバッチによるバックアップ、イベントログ収集を実行する記事を書きました。
上記のコードは「[こちら](https://github.com/nnnmu24/pcmaintBatch)」に格納していますが、左記にあるバッチは実行結果をレポートファイルに出力するようにしています。
今回、これらのファイルを読み込んで画面に出力するPC運用情報表示アプリケーションをElectronで作成したので記事にしたいと思います。

# 画面について
画面はこのようになっています。
![PC保守情報1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409741/e88521af-91c4-42ed-c441-31e753331059.png)

- 1つの枠で、1つの運用バッチの実行結果を示します。
- 成功や異常なしは青、異常がある場合は赤で表示します。
- 詳細情報がある場合は枠内右に表示します。

枠をクリックで詳細情報の非表示/表示が切り替わります。すべての詳細を非表示にするとこのようになります。
![PC保守情報2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409741/316b939e-32f1-9897-50d2-578aea2155a8.png)

# アプリケーションの動きについて
PC運用情報表示アプリケーションは、各種運用バッチが出力するレポートファイルを読み込んで表示します。
イメージ図です。難しい処理はしていません。
![PC保守情報3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409741/9196239a-6a51-0d91-36be-0b200aa3f7a4.png)
複数のレポートファイルは一か所のフォルダ内に格納し決まった形式にする必要があります。

- 「[HEAD]日時,結果」で実行結果を
- 「[REPORT]日時,詳細」で詳細を複数行

例として、こんな感じです。

```
[REPORT][NOTICE!]2020/12/11 23:11:44,警告,(1006 マルウェア対策エンジンが､マルウェアまたは他の望ましくない可能性のあるソフトウェアを検出しました｡)
[REPORT][NOTICE!]2020/12/13 00:39:50,警告,(1006 マルウェア対策エンジンが､マルウェアまたは他の望ましくない可能性のあるソフトウェアを検出しました｡)
[REPORT]2020/12/11 22:04:30,情報,(1001 マルウェア対策スキャンが終了しました)
[REPORT]2020/12/10 03:05:36,情報,(2002 マルウェア対策のエンジンが正常に更新されました｡)
[REPORT]2020/12/13 04:05:41,情報,(2000 マルウェア対策の定義が正常に更新されました｡)
[HEAD]2020/12/13 23:50:06,異常発生
```

「[こちら](https://github.com/nnnmu24/pcmaint)」に公開しているコードを使用する場合、環境に合わせて以下の箇所をカスタマイズします。

- main.js　以下の箇所でレポートファイルのパスを定義しています。  

```
    // ここにレポートファイルのパスを定義する
    event.returnValue = app.getAppPath() + "\\sampleReport";
```
- index.html　レポートファイルを表示する属性です。  

```
    <div class="area_report" id="area_report_bkup"></div>
    <div class="area_report" id="area_report_bwch"></div>
```
- commonPcmaint.js　レポートファイルを読み込む処理です。  

```
    // 通知領域を読み込む
    readNotice() {
        this._parseAndDisplayReport("area_report_bkup", "report_bkup.txt", "バックアップ(データ)");
        this._parseAndDisplayReport("area_report_bwch", "report_bwch.txt", "ブラウザキャッシュ");
```