OmniAICreator/Qiita-1.07M huggingface dataset:
Rubyのメソッドでreturnを省略できる時とできない時

# TL,DR
1. Rubyのメソッドの戻り値で`return`を省略できるのは、**メソッドの最後に記述した式が戻り値になる**という仕様を利用したもの
2. `return`を省略した場合、その後の行に式を書くとその値が戻り値として評価されてしまう
3. 明示的に`return`を書くとその`return`に渡した式が戻り値になり、その後の値は評価されない

# returnがない場合のメソッドの戻り値
Rubyではメソッドの戻り値は`return`に渡した値、もしくはメソッドの最後に記述した式の値を返します。

> メソッドの戻り値は return に渡した値です。return が呼び出されなかった場合は、 body の最後の式の値を返します。 body の最後の式が値を返さない式の場合は nil を返します。

[https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#eval_method](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#eval_method)

またRubyのif式ブロックでは条件式での判定結果が`false`でelseブロックを省略した場合、`nil`を返却します。

> if 式は、条件が成立した節(あるいは else 節)の最後に評価した式の結果を返します。else 節がなくいずれの条件も成り立たなけれ ば nil を返します。


[https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#if](https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#if)

それらを踏まえた上で下記のメソッドを見てください。

## returnを省略したメソッド例1
```ruby
def num_is_zero? num
  if num == 0
    "num is zero!"
  end
end

p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > nil
```
この例では、メソッドの引数として与えられた値が0なら条件式に合致するため、if式ブロックの中の式の値が評価され、その後のメソッド内で評価される式がないため、if式ブロックの値が最終的なメソッドの戻り値として評価されます。

次の例ではif式ブロックの後に式がある場合です。

## returnを省略したメソッド例2
```ruby
def num_is_zero? num
  if num == 0
    "num is zero!"
  end
  "num is not zero!"
end

p num_is_zero? 0
# > "num is not zero!"
p num_is_zero? 1
# > "num is not zero!"
```
これはちょっと予想外に感じるかもしれませんが、**メソッドの戻り値はreturnがない場合、最後に記述した式の値が評価される**という仕様のためです。引数が0の場合は一度はif式ブロック内の`"num is zero!"`という値が評価されますが、その後は`"num is not zero!"`という値が評価されてしまうため、最終的に`"num is not zero!"`という値が戻り値として評価されます。

これを避けるためには明示的に`return`で値を返却する、もしくは**戻り値の後に式を記述しない**ということに気をつける必要があります。

## 明示的にreturnしたメソッド例
```ruby
def num_is_zero? num
  if num == 0
    return "num is zero!"
  end
  "num is not zero!"
end

p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > "num is not zero!"
```
この例では明示的に`return`した為、引数として与えられた値が0の場合はif式ブロックの`"num is zero!"`が戻り値として評価され、それ以降の式は評価されません。引数が0以外の場合はif式ブロックで`nil`の値が評価された後に`"num is not zero!"`が評価されるのでこの値が戻り値になります。

今回のようなif式で判定後に値を返すメソッドの場合は、if式でfalse判定後の処理を`else`を省略して`end`の後に書くのではなく、`else`ブロックに値を記述する方が明瞭に書けます。

## elseでfalse時の値を明記した場合
```ruby
def num_is_zero? num
  if num == 0
    "num is zero!"
  else
    "num is not zero!"
  end
end

p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > "num is not zero!"
```
#まとめ
RubyやRailsでよく見かけるメソッドの戻り値の`return`省略は**メソッドの最後の式の値が戻り値として評価されるという仕様を利用したもの**であることを念頭に置くこと。
その為、明示的に`return`したメソッドから`return`を省略する場合は戻り値を返した後の行に式が存在しないことを確認すること。
ABC125 - C - GCD on Blackboard(300点)

#問題概要
[問題へのリンク](https://atcoder.jp/contests/abc125/tasks/abc125_c)

$N$  個の整数 $A_1$,$A_2$,...,$A_N$が並んでいる。$N$個の整数からある一つの値を任意の値に書き換える。
書き換えた後の $N$ 個の整数の最大公約数の最大値を求めよ。


#制約条件
- 入力は全て整数である。
- $2≤N≤10^5$
- $1≤A_i≤10^9$

#考えたこと
この問題において「ある値を書き換える」という行為は「ある値を排除する」と同義。最大公約数の最大値を求めるので書き換える値はその値を排除した$N-1$個の整数の最大公約数の倍数である任意の値に書き換えればよいので。

例えば入力例1だと 7 6 8 で答えは7を書き換えて2となります。この時7をどんな値に書き換えるかは2の倍数であればなんでもいいわけです。

となると、$N$個の整数の値についてその値がない場合の最大公約数をそれぞれ求めて、最大値を求めればよい。これを毎回最大値を求めていたら計算時間は圧倒的にオーバーするので、累積和的なのりで、ある値 $A_i$ に対して区間$0$ ~ $i-1$と$i+1$ ~ $n-1$の最大公約数をそれぞれ予め求めておく。

こうすれば計算量 $O(N)$ で答えを求めることが可能。

累積和的な考え方についてはTwitterで共有されていた以下の図がすごくわかりやすいです。
https://twitter.com/armeria_betrue/status/1122134567765233665

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326440/f3e2969a-6b12-ca23-3054-625699ffe73e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326440/f3acdd0c-84b2-fe30-ad41-90f5e1b0b7ed.png)



#解答

```c.cs
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args) {
        int n = int.Parse(Console.ReadLine());
        List<int> a = Console.ReadLine().Split().Select(int.Parse).ToList();
        Console.WriteLine(solve(n, a));
    }
    static int solve(int n, List<int> a) {
        int[] lgcd = new int[n-1];
        lgcd[0] = a[0];
        for(int i = 1; i < n-1; i ++) {
            lgcd[i] = Gcd(a[i],lgcd[i-1]);
        }
        a.Reverse();
        int[] rgcd = new int[n-1];
        rgcd[0] = a[0];
        for(int i = 1; i < n-1; i ++) {
            rgcd[i] = Gcd(a[i],rgcd[i-1]);
        }
        a.Reverse();
        int[] ans = new int[n];
        ans[0] = rgcd[n-2];
        ans[n-1] = lgcd[n-2];
        for(int i = 1; i < n-1; i ++) {
            ans[i] = Gcd(lgcd[i-1], rgcd[n-2-i]);
        }
        return ans.Max();
    }
    static int Gcd(int a, int b) {
        if (a < b) return Gcd(b, a);
        while (b != 0) {
            var tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
}
```
便利なツール


# windows向けツール
--- 
## ファイラー・クリップボード監視
--- 
### Clover
https://www.vector.co.jp/soft/winnt/util/se502684.html
エクスプローラーにchromeライクなタブやお気に入りの機能を追加する。
ウインドウの分割や前回開いていたページの復元などの機能もあって便利。
ディスプレイの倍率を変更してるとWindowsの表示がおかしくなりがち…？
<img width="500" src="https://www.gigafree.net/system/explorer/clover.png">

--- 
### Clibor
https://chigusa-web.com/
クリップボードの履歴管理、定型文管理もできる。
カスタマイズ項目も多くて整形もできたり使いこなせばかなり色々できる。
<img width="500" src="https://chigusa-web.com/wp-content/uploads/2019/03/2016-09-24_16h31_28.png">

--- 
## エディタ系

--- 
### サクラエディタ
フリーの高性能エディタ。
よく使う便利な機能

* 矩形選択 Alt + マウスで範囲指定　or Alt +　F5
* ソート
* 重複削除

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108016/5fdb3f02-a1fa-7934-f45e-0a956a9db679.png">

--- 
### 秀丸エディタ
シェアウェアの高性能エディタ。
サクラエディタではできないGrepして置換が便利で使ってる。
<img width="500" src="https://hide.maruo.co.jp/software/hidemaru8/image/hm_main.png">

--- 
### Atom
プロジェクトとしてフォルダを開いたり内部でファイルの行き来ができる。開発向け感が強い。
OSSということもあり、拡張をみんなこぞって作っている為できることは多岐にわたる。
だが、残念ながらAtomのバージョンアップに追従できてないものも多く、拡張を大量に入れてしまうと常にどれかしらで警告が出る状態に…。
<img width="509" src="https://user-images.githubusercontent.com/378023/49132478-f4b77680-f31f-11e8-9e10-e8454d8d9b7e.png">


--- 
## ファイル比較ツール

--- 
### df
昔からあるファイル比較ツール。
比較方法の切り替えや、行の類似度の設定などができるため、色々な条件に合わせて比較をすることができる。
サイトにはwindows2000までの対応環境となっているがwin10でも問題なく動いている。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108016/80818536-e86c-335e-669f-665d9dcb28e8.png">

--- 
### WinMerge 
ファイル比較といえばこれ。
エディタモードにして
3ファイル比較が便利。
<img width="500" src="https://forest.watch.impress.co.jp/library/img/review/10437/winmerge.png">

--- 
## SSH接続ツール

--- 
### TeraTerm
標準的なターミナルツールのイメージ。
マクロも組めるし、貼り付け時の改行警告もある。
<img width="500" src="https://static-cdn.osdn.net/thumb/g/3/117/800x600_0.png">

--- 
### PuTTY
TeraTermよりも高機能。接続ホスト毎に設定を保存できる。
貼り付け時の改行警告が無い…。
<img width="500" src="https://images.sftcdn.net/images/t_app-cover-l,f_auto/p/6a5919fa-96d1-11e6-b8e8-00163ec9f5fa/3816171243/putty-screenshot.jpg">

--- 
### poderosa
https://ja.poderosa-terminal.com/
画面分割に対応。
<img width="500" src="https://ja.poderosa-terminal.com/wp-content/uploads/2016/07/feature-split.png">

--- 
### RLogin
上の3つのいいとこどり。
加えて接続先がタブで管理できて、設定をiniファイルに出力できる。
その為、他のメンバにも接続先情報をファイルで渡せる。

--- 
## スクショツール

--- 
### Winshot
クリップボード保存、ファイル保存、定期実行などスクリーンショットでやりたいことは大体できる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108016/3710735c-0f1f-fdc6-83bc-51cec451e571.png">

--- 
### LICEcap
gif動画でのスクショが取れる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108016/c88b6eb8-bb09-9b2a-a675-179babe3bbb6.png">

--- 
### Snipping Tool
windows標準で入っているスクリーンショット取得ツール
矩形選択もできる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108016/789c532f-7cf8-2656-df0a-9687f2ca6a90.png">
【Processing】標準エディタを使わないで外部ライブラリを導入する

Processing 3.5.3で音声ファイルを再生する際は[minim](https://github.com/ddf/Minim)を使うけど、VScodeなど外部エディタを使用していると詰まったのでメモ。

# とりあえずimportしてみる
「minimはProcessingの標準ライブラリです」とか書いてあったのでjava.textみたいなテンションで使えるかなと思いそのままビルド。

~~~java
import ddf.minim.*;

Minim minim;
AudioPlayer player;
~~~

もちろんエラーが出ました。

~~~
No library found for ddf.minim
Libraries must be installed in a folder named 'libraries' inside the sketchbook folder (see the Preferences window).
test.pde:0:0:0:0: The package “ddf” does not exist. You might be missing a library.
~~~

ここからが詰みポイント。
エラーには
**「ライブラリはスケッチブックフォルダの'libraries'の中にインスコしてね！」**
的なことが書いてあるので、その通り[Github](https://github.com/ddf/Minim)からminim.jarを落として、作ったlibriesフォルダに入れてビルドしてみた。しかし……

~~~
No library found for ddf.minim
Libraries must be installed in a folder named 'libraries' inside the sketchbook folder (see the Preferences window).
~~~

動かない。これはおかしい。
もうちょっと調べてみたら解説してくださっているページがありました。

#解決編

[N.Lab processing ライブラリ](http://nlaboratory.blogspot.com/2009/12/processing.html)

>あーもうどうなんだと思ったので調べてみるとどうもこの件で困ってる人はいますね。
そりゃそうですよ、正解はデバッガの説明と違いますから。

>正解は
>＜スケッチのあるディレクトリ＞/code/controlP5.jar
違う！違うじゃないですか、説明と。

えー……



ということで、Procesisngで標準エディタのinstall機能を使わずに外部ライブラリを使うには、
__.pdeと同じ階層に'code'フォルダを作り、その中にjarファイルを入れる__とOKです。これで動きました。エラーは信じちゃいけないね。
【GAS】Gmailで自由に転送する

#動機
Gmailでは特定のメールを転送することは出来る。しかし相手側に許可を求めるメールが送信され手続きが必要であり非常に面倒。それでいて細やかな変更はできない。そこでGASの力で自由に転送する。
#GAS
```javascript
function transferEmail() {
  transferEmailBySearch('fuga@example.com', 'from:(hoge@example.com)', 'hogeについての転送')
  
  function transferEmailBySearch(address, searchWord, subject) {
    const now = Math.floor(new Date().getTime()/1000); 
    const intervalTime = 8 //8時間毎に実行されるように設定してください
    const term = now - 3600 * intervalTime; 
    
    const str = searchWord + ' ' + 'after:' + term;

    const myThreads = GmailApp.search(str, 0, 30);
    const myMsgs = GmailApp.getMessagesForThreads(myThreads);
    
    if(myMsgs.length == 0)
      return null;
    
    myMsgs.map(function(msgs) {
      const msg = msgs[0];   
      MailApp.sendEmail({
        to: address,
        subject: subject,
        body: 'お世話になっております。\n\n以下転送内容です。よろしくお願いいたします。\n\n' +
              '日時：'+ msg.getDate() + 
              '\n送信元：' + msg.getFrom() + 
              '\n件名：'+ msg.getSubject() + 
              '\n\n' + msg.getPlainBody(),
        attachments: msg.getAttachments()
      });
    });
  }
}
```
#コメント
処理はGmailで8時間毎に検索をかけてスレッド取得→指定したアドレスに転送だけです。
本当はmyMsgsのスレッドすべてのメールに対して受信時刻を確認しなければ転送漏れが出るかもしれない。
#参考文献
Gmail Apps Script - Gmail Service | Apps Script | Google Developers
https://developers.google.com/apps-script/reference/gmail/
公式のリファレンス。必読。
RealmSwiftのidについて

RealmSwiftでのidの扱いは少し注意しないといけません
idのオートインクリメント機能がないんです

idの使い方を何パターンか表記したいと思います。

####①UUIDStringを使う

idは基本的にはIntで扱うと思いますが、オートインクリメントしないのであれば、一意な値であれば問題ないと思います。
ここでは`NSUUID().UUIDString`を使い、ユニークなidを作成します。

```swift:test.swift
class Test: Object {
    
    @objc dynamic var id : String = NSUUID().uuidString
    @objc dynamic var createAt = Date()

　　// IDをプライマリキーにする
    override static func primaryKey() -> String? {
        return "id"
    }
}
```

モデルの定義でidをString型に設定します。
これでユニークな値になるので、idが重複することは無く、idで検索や更新ができます。
ただ、1点注意したいのはidでソートはできなくなります。
そこで、`createAt`を定義し、作成日時でソートするようにしています。
もしくは別のidを作成し、モデルが作成される度に+1していく値を持っておくのもいいかもしれません。

####①オートインクリメント機能の実装

オートインクリメント機能は実装で補うことができます。
どうしてもidをInt型で使いたい場合はこちらの方法を取ることになるとおもいます。

```swift:test.swift
class Test: Object {
    
    @objc dynamic var id : Int = 0

　　// IDをプライマリキーにする
    override static func primaryKey() -> String? {
        return "id"
    }

    func save() {
        let realm = try! Realm()
      
        try! realm.write {
            if self.id == 0 { self.id = self.newId()}
            realm.add(self, update: true)
        }
    }

    // 現在存在する最後のidがあれば、＋1、なければ1を設定する
    static func newId(realm: Realm) -> Int {
        if let task = realm.objects(Task.self).sorted(byKeyPath: "id").last {
            return task.id + 1
        } else {
            return 1
        }
    }
}
```

上記のように登録する際にidを+1にして登録します。
更新か登録かは呼び出し先で制御してください

ただ、この方法を使うには条件があります。
削除しないことが前提です。
例えば、idが1のデータを削除した場合、次に作られるデータはidが1のデータになります。
つまり、**欠番がありません。**

結果的にidでソートしても想定外の並び順になることがありえます。

2つの方法を記載しましたが、削除しないというのはあまりないと思うので、UUIDStringを使う方が現実的かと思います。


######参照

[公式ドキュメント](https://realm.io/jp/docs/swift/latest/)
Leetcode #61: Rotate List

```swift
func rotateRight(_ head: ListNode?, _ k: Int) -> ListNode? {
    var ar = [Int]()
    var current = head
    while current != nil {
        ar.append(current!.val)
        current = current?.next
    }
    for i in 0..<k%ar.count {
        ar.insert(ar.removeLast(), at: 0)
    }
    current = head
    for i in 0..<ar.count {
        current!.val = ar[i]
        current = current?.next
    }
    return head
}
```
railsアプリ開発時にやったSEO対策メモ

# 概要

railsでQAサイトを作った際のSEOメモ

# パンくず設置

gretelを導入。

# httpsリダイレクト

```ruby:config/enviroments/production.rb
config.force_ssl = true
```

上記でhttpsにリダイレクトされるようになる。httpとhttpsどちらにもアクセスが有るとgoogleの評価が分かれるのでリダイレクトさせる。

# tag

metatagを導入して下記の対策を行う。導入方法は下記記事に記載。

https://qiita.com/you8/items/fa546663a514e7552791

## devise周りのnoindex化

```
<% set_meta_tags noindex: true %>
```

deviseを導入するとuser登録周りのページが自動で作られるがこれらのページはindexされてもしょうがないのでmetatagでnoindexに。

## titleのユニーク化

SEO的にはtitleはユニークなものにしたほうがいい。違うページだと認識しにくいので。これはmetatagで下記のようにviewごとに書いて出し分けるのが一番ラクそう。

```
<% set_meta_tags title: "タイトル１" %>
```
RPPL

RPPLとは、Read Parse Print Loopの頭字語である。(今考えた。)


次を`~/.pryrc`に追記する。[^1]


```ruby
$__is_pry_rubyvm_ast_mode = false

def ast!
  $__is_pry_rubyvm_ast_mode = !$__is_pry_rubyvm_ast_mode
end

Pry.config.hooks.add_hook(:before_eval, :"RPPL") do |code, _pry|
  next if code == "ast!\n"
  next unless $__is_pry_rubyvm_ast_mode

  x = code.inspect
  code.clear
  code << "RubyVM::AbstractSyntaxTree.parse(#{x})"
end
```

そしてpryで`ast!`を実行する。
するとpryに打ち込んだコードがASTとなって出力されて、便利である。

```
$ pry
[1] pry(main)> 1 + 1
=> 2
[2] pry(main)> ast!
=> true
[3] pry(main)> 1 + 1
=> (SCOPE@1:0-1:5 tbl: [] args: nil body: (OPCALL@1:0-1:5 (LIT@1:0-1:1 1) :+ (ARRAY@1:4-1:5 (LIT@1:4-1:5 1) nil)))
[4] pry(main)> 
```


https://qiita.com/hanachin_/items/d744e322b4a778574ed7 を参考にしたり、アイディアを得たりしている。


簡単な解説
===


pryは`before_eval`フックでコードを実行する前にフックを実行できる。

```ruby
    exec_hook :before_eval, code, self

    result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
```

https://github.com/pry/pry/blob/bec4ae4e55b911742d45c8f50a080f940bce98ce/lib/pry/pry_instance.rb#L353-L355

フックにはevalする予定の文字列が渡される。
そしてこの文字列はevalにも同じオブジェクトが渡されるため、オブジェクトを破壊的に書き換えればpryが実行するコードを変えることができる。



文字列の書き換えは、`String#clear`と`String#<<`を使っている。clearで文字列を空にして、`<<`でパースを行うコードを書き加えている。



---


雑に実装しただけだしまだ試しただけなので便利なのかもよくわからないが、ひたすらASTを観察したい時には便利な気がする。
ぱっと思いつく課題を挙げれば、取得したASTに対してメソッドを呼び出したい(`RubyVM::AbstractSyntaxTree::Node#children`など)という需要は容易に考えられるが、この実装だとその需要を満たすことはできない。
真面目に使うのであれば、その辺を改善していくと良いだろう。

より良い実装やアイディアがあったらぜひ教えてほしい。


[^1]: なおこのコードのライセンスはCC0とする。 https://creativecommons.jp/sciencecommons/aboutcc0/
SSDに不良ブロックができても諦めてはいけない件

# はじめに(結論)
SSDで不良ブロックができたけど、「chkdsk ドライブ名 /r」コマンドを懲りずに5回叩いたらなおった。諦めないことが必要だと伝えたい。

# 現象
Hyper-Vの仮想クライアントを格納しているSSDの調子が悪いと思ってホスト側のイベントログを確認したら↓みたいなエラーが大量に出力されていた。ｵﾜﾀ＼(^o^)／
![不良ブロック.png](https://qiita-image-store.s3.amazonaws.com/0/167027/92d730fb-6da2-675d-3ecb-a3caeacf56a6.png)
VHDXをコピーしようにも不良セクタに起因しているであろうエラーが出て手詰まり。

# SSDのスペック
Crucial
容量：512GB
使用容量：250GB

# ドライブ構成
以下の通りWindowsとUbuntuの仮想マシンが格納さているだけ。

```
e:\>dir /s /b
e:\Development
e:\ubuntu2
e:\Development\Virtual Hard Disks
e:\Development\Virtual Machines
e:\Development\Virtual Hard Disks\Development.vhdx
e:\Development\Virtual Machines\E14C24B0-903E-4FEE-89CB-8FABC4C18F29
e:\Development\Virtual Machines\E14C24B0-903E-4FEE-89CB-8FABC4C18F29.vmcx
e:\Development\Virtual Machines\E14C24B0-903E-4FEE-89CB-8FABC4C18F29.VMRS
e:\ubuntu2\Snapshots
e:\ubuntu2\Virtual Hard Disks
e:\ubuntu2\Virtual Machines
e:\ubuntu2\Snapshots\37785E30-6F75-4B18-9580-2AA7C7CC5D78
e:\ubuntu2\Snapshots\66A3B9E6-35DB-4DCA-83DA-E2D271832587
e:\ubuntu2\Snapshots\7F5DE175-54A8-439A-872A-D5C6613E944B
e:\ubuntu2\Virtual Hard Disks\ubuntu2.vhdx
e:\ubuntu2\Virtual Machines\5C707328-A04E-41A0-A41B-7BE9DF437FB7
e:\ubuntu2\Virtual Machines\5C707328-A04E-41A0-A41B-7BE9DF437FB7.vmcx
e:\ubuntu2\Virtual Machines\5C707328-A04E-41A0-A41B-7BE9DF437FB7.VMRS
```

# 対処内容
## データのバックアップ
VHDXのマウント自体はギリできたので、必要そうなデータをとりあえずバックアップ領域に退避した。Microsoftアカウントで入っていたためユーザープロファイルの領域のデータ(特にデスクトップフォルダ)のバックアップは諦めていたが、意外に簡単にデータをみることができた。

## chkdskコマンドの実行
ディスクがやばい時の必殺奥義、以下のコマンドを叩いたよ。

```
chkdsk e: /r
```

時間にして、約１〜２時間くらいかかった。ちなみに、自分の場合「進行状況が46/240完了」のまま50分以上変化なかったけど、ググった感じ気にしたら負けらしい。
![WaitChkdsk.png](https://qiita-image-store.s3.amazonaws.com/0/167027/ba9ab53e-c6da-7016-8611-72886f3688a5.png)

## chkdsk e: /r　のディスク負荷
基本的に98%〜100%に張り付く。実行前にバックアップ必要。
![Stress.png](https://qiita-image-store.s3.amazonaws.com/0/167027/9b983249-294b-5b87-f986-925f2f8a8e99.png)

## 不明なエラーが発生
「不明なエラーが発生しました 766f6c756d652e63 470」がでてきた。
![error.png](https://qiita-image-store.s3.amazonaws.com/0/167027/9562241d-329f-a254-1242-f9e66e6bf540.png)
ググっても特に有益な情報が無く、いよいよ詰まった。。。

## 諦めることなく何回もchkdskを実行
不明なエラーが4回連続出力されたけど、5回目でなんかうまくいった。。。なぜうまくいったのか、理由は不明。

# フォーマット
このまま使い続けるの怖いからフォーマットを決意。

## フォーマットの種類
Windowsには

* 普通のフォーマット(フルフォーマット)
* クイックフォーマット

がある。

##クイックフォーマットとフルフォーマットの違い
この２つの違いは、[Western Digitalのサポートサイト](https://support.wdc.com/knowledgebase/answer.aspx?ID=1217&lang=en)曰く、「バッドセクタをスキャンするかどうか？」であり、クイックフォーマットは「既に１回でもフォーマットされていたこと、そして、ハードディスクにダメージがないと保証できる」時に使うのが良いとのこと。
また、こんなことも書かれていた。

> 
If you installed Windows on a partition that was formatted by using the Quick format option, you can also check your disk by using the chkdsk /r command after the installation of Windows is completed.

意訳すると、「もしクイックフォーマットしたならWindowsのインストール後chkdsk /r　流した方がいいよ」とのこと。これってつまり、フルフォーマットを選択したら大量の読み書きが発生するってことなのか？そしてchkdskとフルフォーマットは同じことしてるのか？

##大量に読み書きしているのか？
Crystal Disk Info使って実際に読み書きが行われているか試してみた。。。かったけど、時間がないので今度実行してみたいと思います。ただ、他のサイトをみてもやってることはchkdskらしいので大量のディスクIOが走るっぽい。つまり、一番最初にSSDをフォーマットするときはクイックフォーマットで良さそうな気がします。また、今回はバッドセクタがありそうだったのでフルフォーマットしました。

# 最後に
Windowsの青い画面をもう見たくないでござる。
たとえば、SIerの正社員SEが辛いというネガティブな理由だけで、フリーランスエンジニアに転向しない方が良いケースを考えよう

近年、SNSやブログのトレンドを受け、SEを辞めてフリーランスエンジニアを目指したいと考える方もいるかもしれません。
しかし、フリーランスエンジニアそのものへの転職の際に、一時的な年収だけで判断してしまうのが危険だということをお伝えしておかないといけないと思っています。
正社員だからこそ得られる待遇がなく、フリーランスエンジニアになるとかえって不自由になってしまうケースもあります。
世の中では、SIerが批判され、フリーランスエンジニアが、フリーランス業界を過度に持ち上げようとしている風潮があります。
そのため、フリーランスエンジニアになることで、実質的なキャッシュのダウンに繋がる事例をしっかり分析し、転職に後悔してしまう事例を増やさないように公平に解説すべきだと思い、今回記事にしたいと思います。


# フリーランスの働き方、知られざるデメリット
## 残業や休日手当がないケースがある
フリーランスの場合、残業や休日の時間外手当が出ない場合があります。

ただし、ITフリーランスのような方で、客先に常駐するような準委任契約の場合は、雇用に近い扱いであるという判断のため、時間外手当がほとんどのケースで出ます。

ただし、その際も、契約書に手当を支給する旨が記載されていることが条件であるため、契約書をよく確認することが必要でしょう。

## 税金の源泉徴収がない
フリーランスの場合、以下のような税金を、自分で納めなくてはなりません。

* 所得税
* 住民税
* 個人事業税

また、これらは自分で計算し、納税する義務があります。

## 有給休暇がない
フリーランスの場合、有給休暇がありません。

正社員の場合、有給休暇の日数は、最大で20日支給されます。

つまり、1年で20日分の有給休暇があるということは、約11ヶ月の労働で、12ヶ月分の給料を受け取らないといけないという計算になります。

つまり、有給休暇だけでも、正社員の1,1倍くらいの稼ぎを考えなくてはいけません。

## 社会保険(の一部)がない
フリーランスの場合、社会保険の一部がありません。

一般的に社会保険と言われるものは以下があります

* 健康保険
* 厚生年金保険
* 雇用保険
* 介護保険
* 労災保険
* 健康保険は、フリーランスは国民健康保険に入るケースが多いと思います。

しかし、そのほかの4つ(厚生年金保険、雇用保険、介護保険、労災保険)については加入することができません。

そのため、これらの恩恵を受ける事ができないデメリットがあると言えるでしょう。

特に、社会保険料の半分は会社に支払ってもらう正社員に比べ、フリーランスは全額自己負担になります。

通常、正社員の社会保険料を約3割(自己負担は1.5割)と考えると、フリーランスは、国民健康保険だけで1割程度は負担することになるため、長期的な働けなくなった場合のリスクは大きいと言えるのではないでしょうか。

## 育児休職の際の育児休業給付金がない
フリーランスになった場合、育児休業給付金がありません。

雇用保険の対象外になるため、育児休業という考えがありません。

しかも、出産や育児による休業期間も社会保険料を支払う必要があります。

ただし、出産一時金(42万のやつです)などは支給されますし、2019年度以降は産前6週間・産後8週間に相当する4ヶ月間に関しては、2019年4月よりフリーランスの方もの国民年金保険料の支払いが免除になる予定です。

## 退職金がない
フリーランスの場合、確定給付型年金に基づいた退職金がありません。

大卒が勤続35年以上経て退職した場合、平均して2000万程度の退職金をもらえているようです。つまり、年間60万弱の収入をプラスして考えても良いはずです。

## 営業活動が必要
フリーランスの場合、仕事をもらうまで、もしくは契約が満了したあとのブランク期間で手取りゼロになるリスクがあります。もしくは、そうでなくても次の契約先を探すという労働時間が発生します。

その期間が、1年に1ヶ月発生すると仮定すると、さらに1.1割増しの賃金が必要と言えるでしょう。

# フリーランスのメリット
## 仕事を選べること
では、そこまでリスクを取ってしても、フリーランスになって得られるメリットってなんでしょうか？

フリーランスのメリットは、なんと言っても仕事を選べるところでしょう。

ITを例でいうと、たまたま所属することになったプロジェクトが、レガシーシステムの保守だとしたら、自分が成長する機会としては大きく損失となってしまいます。

その点、そういった案件はフリーランスの場合断れば良いだけですし、その辺は自由がききます。

# 結局手取りはいくら残るの？
通常の期間は、月収が上がること以外で、税金の項目的に正社員とそこまで変わらないかなーって気がします。

参考程度に、式としては大体以下のような感じになるかと思います。

```
手取り月収額 ＝ 年間総収入金額－（所得税＋住民税＋個人事業税＋消費税(年収1000万以上の場合)＋国民年金保険料＋国民健康保険料＋介護保険料）
```

ただし、先述の通り、通常の手取り以外のリスクがあるので、さらに以下のような大きい手当を考慮する必要があるでしょう。

```
有給休暇の日数 + 厚生年金 + 育児休業給付金 + 介護休業給付金 + 失業手当 + 障害手当 + 退職金 + (営業活動のブランク1ヶ月）
```

# まとめ
この記事では、正社員と比較したフリーランスのデメリットについて解説させていただきました。

フリーランスになる場合は、正社員でないと得られないメリットをいろいろ損失してしまうことがわかっていただけたかと思います。

安易に案件の月収ベースで考えずに、トータルで考え、正社員にとどまった方が良いかも何度も検討して、十分に自分に合うかを検討した方が良いでしょう。

特にネットには最近、フリーランスエンジニアを過剰に評価した意見が多いので。

# 最後に
Youtubeの方で、SIerエンジニア・ITコンサルタント・社内SEの正社員エンジニアのキャリアに興味のある方たち向けの、「[ぴなもとch](https://t.co/B1CZUQ77dS)」というチャンネルをやっています。もしご興味ございましたらチャンネル登録してみて頂けると大変嬉しいです。

ブログ「[ITエンジニアのソフトスキル](https://minimalist.pinamoto.com/)」・Twitterの方でも情報を発信しておりますので、もし宜しければフォローしていただけたら幸いです。
[@Pina__KWSK](https://twitter.com/Pina__KWSK)
Leetcode #59: Spiral Matrix II

```swift
func generateMatrix(_ n: Int) -> [[Int]] {
    var matrix = Array(repeating: Array(repeating: 0, count: n), count: n)
    var top = 0
    var bottom = n - 1
    var left = 0
    var right = n - 1
    var num = 1
    while true {
        if left > right {
            break
        }
        for i in left...right {
            matrix[top][i] = num
            num += 1
        }
        top += 1
        if top > bottom {
            break
        }
        for i in top...bottom {
            matrix[i][right] = num
            num += 1
        }
        right -= 1
        if left > right {
            break
        }
        for i in stride(from: right, through: left, by: -1) {
            matrix[bottom][i] = num
            num += 1
        }
        bottom -= 1
        if top > bottom {
            break
        }
        for i in stride(from: bottom, through: top, by: -1) {
            matrix[i][left] = num
            num += 1
        }
        left += 1
    }
    return matrix
}
```
多対多　DBに値入らない時

real_shopテーブル----real_shop_expert_collectionテーブル（中間）----expert_collectionテーブル

それぞれテーブルを作る

```real_shop.rb
  has_many :real_shop_expert_collections
  has_many :expert_collections, through: :real_shop_expert_collections
```


```expert_collection.rb
  has_many :real_shop_expert_collections
  has_many :real_shops, through: :real_shop_expert_collections
```

```real_shop_expert_collections.rb

  belongs_to :real_shop
  belongs_to :expert_collection
```



##エキスパートコレクション内でリアルショップに登録してある内容をチェックボックスで全表示させたい！


```expert_collections/_form.html.erb

<table class="form_area " id="is_shop_area_1">
<tr>
<th scope="row">対象店舗</th>
<td>
<% for shop in current_site.real_shops %>
<%= check_box_tag "shop_ids[]", shop.id, @expert_collection.real_shops.ids.include?(shop.id), :id => "shop_id_#{shop.id}" , :class => 'shop'%>
<%= label_tag "shop_id_#{shop.id}", shop.name %>
<% end %>
<% if current_site.real_shops.present? %>
<br />
<input type="button" value="全て選択" id="shop-true" class="set_all_button" /> <input type="button" value="全て解除" id="shop-false" class="set_all_button" />
<% end %>
</td>
</tr>
</table>

```

check_box_tagのリファレンス
 `check_box_tag(要素名 [, 値, checked = false, オプション])`


![スクリーンショット 2019-05-07 19.15.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265805/18ffb256-4bed-3316-0868-b5e63dc3e726.png)

realshopの店舗から選択したエキスパートコレクションがshop_ids[]に格納される

なので

##多対多の要素をDBに登録したい

 ```expeert_collections_controller.rb

  def new
    @expert_collection = ExpertCollection.new
  end

  def create
    @expert_collection = ExpertCollection.new(params[:expert_collection])
    @expert_collection.site_id = current_site.id
    @expert_collection.real_shops = RealShop.find(params[:shop_ids]) if params[:shop_ids].present?
    if @expert_collection.save
      redirect_to  ar_admin_expert_collections_path, :notice => "エキスパートコレクションを作成しました。"
    else
      render :new
    end
  end

```

createの３行目。`params[:shop_ids]`があったら`@expert_collection.real_shops`に格納
してからsaveすれば中間テーブルに値が入ります。
binding.pryで条件付きでデバッグする

## what 
Railsで `binding.pry`を使って、条件付きで処理を止める方法を知りたい。

Android Studioだとこれがデフォルトでできました。
例えば、何回もアクセスされるエンドポイントで、特定の条件のときにだけエラーが起きている場合、関係ないアクセスのときにも処理が止まってしまうとデバッグするのが面倒です。
（ある料理レシピサイトがあったとして、リストの３ページ目にアクセスしたときだけエラーが起きる場合。１ページめを表示したときにも処理が止まると面倒ですよね。）

## how
まずは、 gemをインストール。

```
gem install pry-byebug
```

デバッグしたいファイルに以下を追加

```
require 'pry'
```

処理を止めたい箇所に以下を記述

```
binding.pry
```

さらに、処理を止めたい条件を以下のように記述

```
binding.pry if page == 3
```

これで `page == 3`のときにだけ処理が止まるようになりました。

## おまけ
### 処理を止めた時に使えるコマンド

- next
    - 次の行を実行（メソッドは実行される）
- step
    - 次の行を実行、メソッドなら中に入る
- continue
    - プログラムを実行し、pryを終了
- break
    - break `数字`=> 数字の行にbreak pointを貼る

### aliasを貼る

以下を `~/.pryrc`に貼り付ける

```
if defined?(PryByebug)
  Pry.commands.alias_command 'c', 'continue'
  Pry.commands.alias_command 's', 'step'
  Pry.commands.alias_command 'n', 'next'
  Pry.commands.alias_command 'f', 'finish'
end
```

### 直前のコマンドを `Enter`キーで繰り返す
以下を `~/.pryrc`に貼り付ける

```
Pry::Commands.command /^$/, "repeat last command" do
  _pry_.run_command Pry.history.to_a.last
end
```
Leetcode #54: Spiral Matrix

```swift
func spiralOrder(_ matrix: [[Int]]) -> [Int] {
    var row = matrix.count
    if row == 0 {
        return []
    }
    var column = matrix.first!.count
    if column == 0 {
        return []
    }
    var top = 0
    var bottom = row - 1
    var left = 0
    var right = column - 1
    var answer = [Int]()
    while true {
        if left > right {
            break
        }
        for i in left...right {
            answer.append(matrix[top][i])
        }
        top += 1
        if top > bottom {
            break
        }
        for i in top...bottom {
            answer.append(matrix[i][right])
        }
        right -= 1
        if left > right {
            break
        }
        for i in stride(from: right, through: left, by: -1) {
            answer.append(matrix[bottom][i])
        }
        bottom -= 1
        if top > bottom {
            break
        }
        for i in stride(from: bottom, through: top, by: -1) {
            answer.append(matrix[i][left])
        }
        left += 1
    }
    return answer
}
```
IPython における「%run hoge.py」と「!python hoge.py」の違い

## TL;DR:
`%run`:
　　.pyの中身をセルに展開して実行したみたいな挙動
　　その後のセルの実行に影響する
`!python`:
　　サブシェルで`python hoge.py`を実行
　　その後のセルの実行には影響しない


## 経緯
[Google Colaboratory](https://colab.research.google.com/)で.pyファイルの実行方法に

```
%run hoge.py
```
```
!python hoge.py
```
の2種類があり、どちらでも実行できる。
両者に違いがあるのかないのかハッキリさせたい。


## 検証
```hoge.py
hoge = 256
```
```piyo.py
piyo = 512
```
```python
print(hoge)  # -> NameError
%run hoge.py
print(hoge)  # -> 256

print(piyo)  # -> NameError
!python piyo.py
print(piyo)  # -> NameError
```

結果：`%run`では名前空間が取り込まれたが、`!python`はそうならない。

Google Colaboratoryで実験する
→　[runPyFile.ipynb - Colaboratory](https://colab.research.google.com/drive/1aOgaiMvug0UPWONRUjAdjcAwxjdt9iAh)


## なぜ？
IPython公式ドキュメントの [IPython as a system shell](https://ipython.readthedocs.io/en/stable/interactive/shell.html#directory-management) の節には
> Since each command passed by IPython to the underlying system is executed in a subshell which exits immediately, you can NOT use !cd to navigate the filesystem.

と書かれている。
> （`!`で始める）シェルコマンドはサブシェルで実行されてすぐに破棄される、よって`!cd`ではカレントディレクトリは変更されない。（意訳）

つまり、`!python`ではpythonがサブシェルで実行されるため名前空間が共有されることはない。


対して、[Built-in magic commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-run) の節には`%run`について

> This is similar to running at a system prompt `python file args`, but with the advantage of giving you IPython’s tracebacks, and of loading all variables into your interactive namespace for further use (unless -p is used, see below).

と書かれている。
> シェルで`python [.pyファイル] -引数...`とやるのに似てるけど、トレースバックと名前空間のロードが付いてきてお得。（意訳）

つまり、`%run`では.pyファイルで用意した変数が次のセル以降でも維持される。
逆に`%run`実行以前に定義していた変数は`%run`の実行で**上書き**される。
（`-p`オプションの挙動と変数の上書きは [runPyFile.ipynb - Colaboratory](https://colab.research.google.com/drive/1aOgaiMvug0UPWONRUjAdjcAwxjdt9iAh) でも実験できる）
【MySQL】ユーザーの作成方法について解説！

# データベースごとにユーザーの権限を分けて管理する
データベースを操作する際に、あらかじめ用意されている「root」ユーザーは、全ての操作（テーブルの削除、追加　など）ができてしまいます。
そのため、新規で作業ユーザーを作成して、ユーザーごとに操作できる範囲を設定する必要があります。

## rootユーザーとは
-  「root」ユーザーとは、あらかじめ用意されているユーザーで、すべての操作（テーブルの削除、追加　など）が可能な権限を持っています。


## 作業ユーザーとは
- 特定の操作のみ行えるように設定したユーザー。（例：テーブルの追加、削除が行える　など）

## ユーザーの権限を分ける理由
- 「root」ユーザーは何でも操作ができてしまうため、誰かが誤って操作をしてしまうとデータが失われる危険性があります。
- そのため、操作できる内容を制限した作業用ユーザーを作成してデータベースを操作します。

# 作業用ユーザーを作成する方法

```sql:
grant all on データベース名.* to ユーザー名@loacalhost identified by 'パスワード';
```
```mysql:実行結果
Query OK, 0 rows affected (0.00 sec)
```
## 解説
- `grant all on`は全ての権限を与えるという意味になります。
Angular8のインストール方法



# _Angular8のインストール_  

by **_Shuichi Ohtsu_** 


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_00.png" width= "640" >



ビデオ解説(日本語）
<https://youtu.be/Y3kNNikdnXs>

ビデオ解説(英語）
<https://youtu.be/J8Jj-sKlS6I>




Angular8のインストールには、

1. プロジェクト単位のインストール
2. システム全体でのインストール(`-g`オプションを指定）

の２通りがあります。

ここでは、システム全体でのインストールをご紹介いたします。

なお、現在Angular7バージョンなどで、開発を行っているシステムでは、このインストールを行わないでください。

現時点すなわち、2019年5月30日時点でインストールを行った場合には、Angular8の8.0.0になります。


--------------------

## システム全体でのインストール(`-g`オプションを指定）


_システム全体でのアップグレード_ですが、まずNode.jsとnpmのバージョンを確認します。

`node --version`と入力します。

`npm --version`と入力します。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_01.png" width= "640" >


--------------------

次にAngular8のインストールを行います。

まず、すでに開発を行っている既存のシステムで以下の作業を行わないでください。

バージョンアップにより稼働できなくなる可能性もありますので、新しいシステムあるいは、テスト用のシステムで行ってください。

まず、既存のAngular CLIがある場合にはそれを削除します。


`npm uninstall -g @angular/cli`と入力します。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_02.png" width= "640" >


--------------------

アンインストールが終わりましたら、Angular8のインストールを行います。

`npm install -g @angular/cli`と入力します。

  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_03.png" width= "640" >


このコマンドで、Angular7がインストールされてしまう場合には、以下のように直接バージョン番号を指定します。2019年5月30日現在での最新バージョンは、`8.0.0`ですので、`@`の次にこのバージョン番号を指定します。

`npm install -g @angular/cli@8.0.0`と入力します。


--------------------

ここでインストールされたバージョンを確認します。

`ng --version`と入力します。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_04.png" width= "640" >



Angular8がインストールされていることがわかります。

--------------------

次に適当なプロジェクトを作成して稼働をチェックしてみます。

コマンドラインで`ng new ng8test`と入力します。

ng8testはプロジェクト名であり、この名前は任意です。


--------------------

最初に、ルーティング機能を追加するか否かと問い合わせがありますが、ここでは`y`としておきます。

次に、スタイルシートの形式の問い合わせがありますが、`SCSS`を選択します。

するとプロジェクトの生成が始まります。

このプロセスには若干時間を要します。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_05.png" width= "640" >



--------------------

プロジェクトが生成されましたら、そのプロジェクト・ディレクトリに入ります。

そして、`code .`と入力して、Visual Studio Codeを起動します。

--------------------

次に、`Control+@`キーを押し、ターミナル・ウィンドウを開きます。

--------------------

VS Codeが開きましたら、`Package.json`ファイルを開き、バージョンを確認してみます。

バージョン8が表示されます。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_06.png" width= "640" >



--------------------

ターミナル・ウィンドウで、`ng s -o`と入力して、ローカルサーバを起動し、ブラウザを開きます。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_07.png" width= "640" >



--------------------


Angularのデフォルトのページが表示されました。

ＯＫです。


  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng8_install_08.png" width= "640" >



--------------------

VS Codeに戻り、`Control+c`でローカル・サーバを停止させます。


--------------------

Angular8の稼働を確認できました。

ＯＫです。

--------------------

　  

## Reference


- "Angular Update Guide", 
<https://update.angular.io/>
【Vim】Macで快適にHJKLする

# TL;DR
どうも、最近``.vimrc``を育て始めたニワカVimmerです。

前からVimでの``HJKL``移動を速くしたかったのですが、Macの環境設定で簡単にできたので設定方法を晒します。

# 設定方法
- 「システム設定 > キーボード」でキーボードの設定画面を開きます
- 「キーのリピート」を**「速い」**に振り切ります
- 「リピート入力認識までの時間」を**「短い」**に振り切ります

<img width="537" alt="スクリーンショット 2019-05-07 22.23.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287161/75c1b942-194f-ba4a-e9e6-bbbff4b9d54f.png">

#### 設定はこれだけ！

速くて使いづらいなという方は、「キーのリピート」と「リピート入力認識までの時間」を少し遅くしたりして調節するといい感じになるかと思います。

# まとめ
高速HJKL移動でVim生活がさらに快適になりそうです。
IBM Cloud appsの停止通知メールが届いた場合の対処（ライト・プラン）

#１．IBMCloudからの通知
現在、IBMCloudを使って[ビール女子🍺麦子さん](http://nav.cx/aLo5a15)というLINEBotを開発しているのですが、ある時、IBMCloudから次のようなメールが届きました。

>Your IBM Cloud apps in organization xxxxxxxx will sleep in 4 day(s) because they haven't had any development activity recently. This means that these apps will stop running and won't be accessible to visitors.
  
>Keep your apps running by actively working on them — push updates or perform other development actions.

雑に訳すと、以下のような内容です。（適当ですみません）

>最近開発作業をしていなかったので、IBMCloudのappsが４日以内にスリープになります。appsは停止し訪問者はアクセスできなくなります。

>アップデートするか開発作業をすることで、appsの稼働を継続します。



#２．利用していたリソース
このメールを受け取ったとき次のような状況でした。

**【料金プラン】**
IBMCloudの**ライト・プラン**で使っているため、**「10日間開発なしでアプリを自動停止」**という制限がついている状態です。

**【主な利用機能】**
①Node-RED
②WatsonAssistant
③Visual Recognition　など

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/515b75dc-70f2-bc37-c944-3d85459515f3.png)

#３．状況
このメールを受け取ったとき、毎日のようにWatsonAssistantやNodeREDのメンテナンスを行っており、なぜ「最近開発作業をしていなかった」とみなされているのが理解できませんでした。

まず「IBM Cloud apps」が何を指すのかよくわからなかったのですが、これは**Cloud Foundryサービス欄のnode-RED**を指しているようです。Watson Assistantなどの開発は関係ないようです。

また、どうやら**Node-REDのエディタに直接アクセスしてデプロイする操作は、IBMCloud側には開発作業として認識されない**ようです。

#４．対処方法
Node-REDをIBMCloud側で「開発作業をしている」と認識させるために、ひとまず**再起動する**とことにしました。再起動の仕方も少しわかりづらかったので、手順を記しておきます。

**【再起動手順】**
①対象のリソースをクリック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/31571300-5adc-c965-5d33-780c38c4cf15.png)

②右上の「点々々」のメニューから「再起動」を選択
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/12de2269-2a7d-a17d-22db-c39566649f24.png)

③再起動完了！
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/bac3e4a2-d636-f4df-323c-71d28b080940.png)
トレジャーデータ とTableauの連携

トレジャーデータ を使える環境になったが可視化をどうするか思い
とりあえずTableauのデスクトップ版を２週間限定だが使って見ることした。
なのでprestoを使えるようにして見た。

## 前提

macを前提に書きます、
あとトレジャーデータ のアカウントを保有している
Tableau Desktopをトライアル版でいいので使える

## macでの設定

### ドライバーインストール

https://www.tableau.com/support/drivers
のリンクからPrestoという項目があるのでチェックを入れてダウンロードする。

これを開き Simba Presto 1.1.pkg をインストールする。

<img width="743" alt="スクリーンショット 2019-05-07 21.43.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343871/56ab9444-e59f-ac1a-1871-31a6d5690687.png">

### Tableauでの設定

サーバーへ -> その他 -> Presto

<img width="860" alt="スクリーンショット 2019-05-07 21.54.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343871/1d8063ac-ca46-cffe-0b81-7937a9c98eae.png">

この画面が開かれるので

<img width="395" alt="スクリーンショット 2019-05-07 21.57.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343871/7a601b17-ff9e-c423-db6c-4f609e51ed20.png">

| 項目       |       内容 |
|:-----------------|------------------:|
| サーバー          |  api-presto.treasuredata.com |
| ポート          |            443 |
| カタログ            |              td-presto |
| スキーマ               |                空でいい |
| 認証             |             ユーザー名 |
| ユーザー名          |           TreasureDataのMaster APIKey |
| パスワード          |           空でいい |
| SSLが必要    |           チェックをつける |

TreasureDataのMaster APIKeyは左下にあるボタンからMyProfileを選び
API Keysの項目で自分のパスワードを入力するとAPIKEYが表示されます。

Master keyとWrite-only keyの二つが発行されますがMaster keyの方を入力します。

<img width="667" alt="スクリーンショット 2019-05-07 22.04.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343871/29218d60-94ac-696e-f02b-4d747de80553.png">

サインインができるようになると思いますので下記のような画面が出れば接続成功です。
スキーマなどの項目からトレジャーデータ のDBから任意のデータを取り出せるようになりました。

<img width="805" alt="スクリーンショット 2019-05-07 22.08.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343871/3f8772de-07fa-322d-120b-a2a060b2bfb7.png">

## 最後に

これ以上はあまりやれてないが色々データをグラフでの可視化ができそうで、使いこなせたら結構
楽しそうなことができそうである。
JavaCCのセットアップ手順

# とっても易しいセットアップ手順
職場でどうしても構文解析をしたくなったので、JavaCCというパーサジェネレータを使う機会がありました。
この記事は、JavaCCを使うにあたって、公式ページのGetting Startedなど色々読んでまとめた自分向け手順です。

1. 環境
  以下の環境で動作確認しました。  

    | OS  | JDK | JavaCC |
    |:----|:----|:-------|
    |Redhat Enterprise Linux(RHEL) 6 | 1.6 | 6.0 |
    |macOS Mojave | 1.8 | 6.0 |
    |Windows 10 | 1.8 | 6.0 |

1. 参考
  [公式ページ:Getting Started](https://javacc.org/getting-started)
    
1. ダウンロード
  [公式ダウンロードサイト](https://javacc.org/download)からzipファイルをダウンロードします。
  私の環境では、「Download JavaCC 6.0」というリンクボタンを押すとダウンロードが始まりました。

1. 解凍
  ダウンロードしたzipファイルを解凍します
  解凍先は書き込み権限のあるところならどこでも大丈夫です。
  （私はサーバ側の環境を壊さないよう、以下のようにホームディレクトリ配下に解凍しました。）

    ``` bash:(Linx/Mac)
    ${HOME}/usr/local/tools/javacc-6.0
    ```

    ``` bash:(Windows)
    %systemdrive%%homepath%¥usr¥local¥tools¥javacc-6.0
    ```


1. 実行ファイルの作成
  解凍したディレクトリ(フォルダ)内に"bin"というディレクトリがあります。
  ここに以下のような実行ファイルを起きます。

    ``` bash:${HOME}/usr/local/tools/javacc-6.0/bin/javacc(Linux/Mac)
    #!/bin/bash
    java -cp ${HOME}/usr/local/tools/javacc-6.0/bin/lib/javacc.jar javacc "$@"
    ```

    ``` batch:%systemdrive%%homepath%¥usr¥local¥tools¥javacc-6.0¥bin¥javacc.bat(Windows)
    @ECHO OFF
    java -cp %systemdrive%%homepath%¥usr¥local¥tools¥javacc-6.0¥bin¥lib¥javacc.jar javacc %%*
    ```

1. パスを通します。
  ユーザ環境変数PATHに実行ファイルを置いたディレクトリを追加します。

    ``` bash:Linux/Mac
    export PATH=${PATH}:${HOME}/usr/local/tools/javacc-6.0/bin
    ```

    ``` batch:Windows
    set PATH=%PATH%;%systemdrive%%homepath%¥usr¥local¥tools¥javacc-6.0¥bin
    ```

1. テストしてみます
  上記でセットアップは完了です。
  ここで、動作するかテストしておきましょう。(Windowsについては割愛)

  ``` bash:Linux/Mac(ホームディレクトリを/home/hogehogeとした場合)
  > # まずはPATHが通ったことを確認
  > which javacc
  /home/hogehoge/usr/local/tools/javacc-6.0/bin/javacc
  > # javaccが実行できることを確認
  > javacc
  Java Compiler Compiler Version 6.0_1 (Parser Generator)

  Usage:
      javacc option-settings inputfile

  "option-settings" is a sequence of settings separated by spaces.
  Each option setting must be of one of the following forms:

    ...(実際はもっと長いメッセージが出ます。)
  ```
ケルベロス認証について勉強してみた

先輩「この間の件、ケルベロスが必要だって言われてましたねー」
私　「！？？」

朝一番にそんなこと言われて「えっと、わかりません」と答えた GW 明け、皆さんいかがお過ごしでしょうか？
私は先輩の苦笑を GET したので必死で勉強しております。
きっかけがあると、自分が無知なことがわかっていいですね。精進します。

##ケルベロスと出会った経緯

GW 前に、ようやく検証用のサーバーを用意してもらえました！
本当にありがとう！감사합니다！

なぜ韓国語かって？
用意してもらったサービスが NaverCloud だからです。
日本では全然馴染みのない NaverCloud は、ドキュメントも UI もすべて韓国語 or 英語 Death.

まぁでも、なんとかなるだろ！って思ってログインして create server したらいきなり目の前に立ちはだかってくれたのが、ケルベロスちゃんなのです。
![kerberos.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/a5f30c28-c5bb-6e48-ee2f-3fc427f5094a.png)
（注：イメージです）

##Kerberos ID of the employee does not exist.

「従業員の Kerberos ID が存在しません。」
まぁ、つまり私のアカウントでは使えない、と。
この時点では調べもしなかった Kerberos ちゃん。
スクショ撮って先輩に「ID 発行申請お願いしまーす」ってトークした私。

そして悲劇は GW 明けに起きました。
わからないことには興味を持って接しましょうという教訓ですね。頑張ります。

#ケルベロス認証とは

さて、本題。
ケルベロス認証のポイントはこんな感じ。

- アカウントを認証する方法の一つ。
- 認証されると、チケット（身分証明書のようなもの）が発行される。
- チケットがあれば他のサービスを利用できる（つまりはシングルサインオン）

主に、シングルサインオンを実装するときに使うようです。
シングルサインオンの認証としてケルベロス認証を使用するメリットとしては、セキュリティ面が挙げられます。
他のサービスを利用する際にチケットで認証するので、ID とパスワードの漏洩を防ぐことができます。

また、チケットの盗聴によるなりすましを防ぐために、時刻同期の仕組みが用意されています。
NTP (Network Time Protocol) を使用して、チケット発行側の時計とチケット利用側の時計の時刻が同じになるようにしておけば、チケットのなりすましも防ぐことができます。

###つまりは身分証明書のようなもの

ファンタジーな世界観で認識すると、こんな感じだと思います。

長旅から帰ってきた私。
王国に入るために城門で身分証明書を発行してもらう。

私　「ただいま帰りました。」
役人「（顔を確認して）おお、おかえりなさい。お久しぶりですね」
私　「ようやく帰れました。しばしの休息です。さっそくで悪いのですが。身分証明書を発行してもらえますか？」
役人「早く宿で休みたいですよね。すぐに発行しますよ。では、合言葉をお願いします」
私　「『夢に楽土求めたり』」
役人「OK です。・・・できましたよ。こちらをどうぞ」
私　「ありがとう。（身分証明書を受け取る）ところで、王立図書館で調べ物をしたいのだが・・・」
役人「それでしたら、隣の受付で入館証を発行してもらってください」
私　「ありがとう」

受付へと移動する。

私　「王立図書館の入館証を発行してください」
受付「では、身分証明書を確認しますね。（身分証明書を確認）はい、OK です。では、こちらをどうぞ」
私　「ありがとう。（入館証を受け取る）」

王国内へ入り、王立図書館へ向かう。

門番「王立図書館へようこそ。入館証をご提示いただけますか？（入館証を確認）はい、OK です。どうぞお通りください」

こうして私は、思う存分、本を読みふけるのであった。～ Fin ～

###合言葉は一度だけ

合言葉を言うのは、城門で身分証明書を発行する一度きりです。
その後、王立図書館だろうが騎士団宿舎だろうが、入館証が必要な場合は身分証明書を提示すれば入館証を発行できます。
合言葉を知るのは本人と城門の役人のみ。
情報を知る箇所が少なければ漏れるリスクも減り、万が一漏れた場合でも調査個所が少なくなります。
つまり、万が一には役人を締め上げればいいわけですね（＾＾）

あとは、身分証明書や入館証の偽造ですが、これは魔法（時刻同期）を使って管理すれば偽造は容易にはできません。
なんと強固な認証機能なんでしょう！魔法ってステキ！！(*´▽｀*)

#おわりに

Q.　ケルベロス認証ってなーに？
A.　最初は ID とパスワードで認証するけど、次からは発行されたチケットを使って行う認証のやり方

いやー、知らないことがまだまだたくさんあります。
もっと勉強しないとですね。
ここまで読んでいただき、ありがとうございました！
ではまた！(^^)/

#参考にさせていただきましたm(_ _)m

[聞いたことがある認証について調べてみた](https://qiita.com/horikeso/items/ecb8b59b8bf07e6b9724)
[kerberos認証（「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典）](https://wa3.i-3-i.info/word15908.html)
[Kerberos Authentication（ネットワークエンジニアとして）](https://www.infraexpert.com/study/security18.html)
[ケルベロス認証（Wikipedia）](https://ja.wikipedia.org/wiki/ケルベロス認証)
[【 Network Time Protocol 】  ネットワークタイムプロトコル（IT用語辞典 e-Words）](http://e-words.jp/w/NTP.html)
Nuxt.jsでLottieアニメーションをページローディングで使う

## これは
lottieで作ったアニメーションをNuxt.jsのページローディングで使う方法。


まずlottieで読み込むアニメーションファイルを作成。
ここでは、`loading.json`というファイルで用意した。
保存先は`assets/animation/loading.json`

https://lottiefiles.com/
(サイトに様々なexampleが用意されているので参考に）

## player installation
lottieをwebで使うためにlottie-webというnpmをinstallする。
see https://github.com/airbnb/lottie-web

with npm
`npm install lottie-web`

with yarn
`yarn add lottie-web`

## loading animation component
jsonを読みこむコンポーネントの作成。
使用する際はコンポーネントのjsonを用意したファイルに書き換えると良い。

```loading.vue
<template>
  <div v-show="loading" class="loading">
    <div class="anim" ref="lavContainer"></div>
  </div>
</template>

<script>
import loading from "@/assets/animation/loading.json";

export default {
  data: () => ({
    loading: false
    options: {
      animationData,
      loop: false,
      autoplay: false,
      rendererSettings: ""
    };
  }),
  mounted() {
    this.anim = lottie.loadAnimation({
      container: this.$refs.lavContainer,
      renderer: "svg",
      loop: this.options.loop !== false,
      autoplay: this.options.autoplay !== false,
      animationData: this.options.animationData,
      rendererSettings: this.options.rendererSettings
    });
  }
  methods: {
    start() {
      this.anim.play();
      this.loading = true;
    },
    finish() {
      this.anim.stop();
      this.loading = false;
    }
  }
}
</script>

<style scoped>
.loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: white;
  text-align: center;
  padding-top: 200px;
  font-size: 30px;
  font-family: sans-serif;
  z-index: 9999;
}

.anim {
  height: 100px;
  margin: 0 auto;
  overflow: hidden;
  width: 100px;
}
</style>
```

## loading config setting

nuxt.config.jsに作成したコンポーネントを指定する。
これでページネーション時のアニメーションが実行される。


```nuxt.config.js
export default {
  loading: '~/components/loading.vue'
}
```

https://twitter.com/keng0o_
AtCoderでREとなった時にエラー内容について調査する方法

# 概要
AtCoderで、submitしたコードのテスト結果が`RE`で落ちている時、そのテストがどこで落ちているか、何のエラーで落ちているかを探る手法について書きます。
どこでエラーが発生しているかがどうしてもわからない時に使えます。

## エラー制御を利用する
発生したエラーを捕まえて例外処理を使うことでどこでエラーが発生したかわかります。
任意の箇所にエラーを補足するコードを挟み、その例外処理部で必ず`WA`するようなコードを書きます。
これによって、対象の問題のテスト結果が`RE`か`WA`するかを見ることによってエラー発生箇所を絞り込めます。

さらに、エラー種別がある程度絞り込めているなら
エラー種別を指定して例外処理を書くことで、エラー種別の絞り込みも可能になります。

## 注意事項
submitを大量に繰り返すとシステムの負荷に繋がります。
ここで紹介した手法は、どうしてもわからないときだけ利用してください。

システムに不要な負荷をかける行為はなるべく避けましょう。
pythonのカプセル化とマングリングについて

pythonにはprivate変数はありません。

しかしprivate変数に近いことは実現できます。

##「_」1つのprefix##
PEP8上のコーディング規約としては
「_」1つのprefixをclass内のみで利用する変数とされています。

この変数は```from M import *```とした場合、
importされません。

しかし、この変数は
インスタンス化したオブジェクトからのアクセス時には
物理的な機構はなくカプセル化としての役目は果たせません。


##「__」2つのprefix##
「__」2つのprefixをつけた場合、
ネームマングリング機構が働きます。

Name Manglingとは名前修飾という意味で、
該当のprefixが付いている変数にはpythonコード上で意味が与えられます。

該当の変数名は「_class名」のprefixがついた変数名へと
置換されます。

ただし、これもあくまで変数名が置換されるために
通常のような、インスタンスからの変数名へのアクセスが
できなくなるだけです。
通常よりは硬い実装にはなりますね。

あくまで変数名が変わっているだけなので
置換後の変数名へのアクセスは許します。

本来、ネームマングリング機構は
親クラスと子クラス間での名前衝突を避ける目的の為のもののようです。
(```__init__```や、```__main__```などのメソッドの所属元クラスをはっきりさせる)
    
```python
class HogeHoge:
    _dummy_prv = "hoge"
    __almost_prv = "hoge"

class Main:
    hogehoge = HogeHoge()
    
    # 丸見え
    a = hogehoge._dummy_prv

    # エラー
    b = hogehoge.__almost_prv

    # こうするとアクセスでちゃう
    c = hogehoge._HogeHoge__almost_prv
```

参考
---
[pep8-ja 1.0 ドキュメント](https://pep8-ja.readthedocs.io/ja/latest/)
[python学習講座 プライベートメンバ](https://www.python.ambitious-engineer.com/archives/323)
ディープラーニングガジェット品評会のネタ

[ディープラーニングガジェット品評会](https://connpass.com/event/129065/)で発表するネタをまとめておきます。

私は、[handtracking](https://qiita.com/shinmura0/items/07d976fc13ce774036b8)↓を使った複数のネタを発表する予定です。

![gif1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/e7b714ad-722d-ed9c-2200-7fa20ae0bece.gif)

#ネタ1　夢を叶えるインターフェイス
![ntxbi-8qwsl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/1dcc11d6-a090-6be9-9143-b909751106ed.gif)

詳しくは[こちら](https://qiita.com/shinmura0/items/c9f4b27f2e3ccc122d60)

#ネタ2　「かめはめ波」を支える技術

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">かめはめ波、打ち放題です。<br>【ディープラーニング×OpenCV×ラズパイ】 <a href="https://t.co/FqpszBBF5C">pic.twitter.com/FqpszBBF5C</a></p>&mdash; shinmura0 (@shinmura0) <a href="https://twitter.com/shinmura0/status/1135050040685125632?ref_src=twsrc%5Etfw">2019年6月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

詳しくは[こちら](https://qiita.com/shinmura0/items/53116fcddded3961a54f)

#ネタ3　組立検査器
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">異常作業その１（Qiita用）。MobileNet V2 SSDlite + BayesianOptimization + KalmanFilter <a href="https://t.co/MSXQzANybK">pic.twitter.com/MSXQzANybK</a></p>&mdash; shinmura0 (@shinmura0) <a href="https://twitter.com/shinmura0/status/1144088836110053376?ref_src=twsrc%5Etfw">2019年6月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


詳しくは[こちら](https://qiita.com/shinmura0/items/09ed686466f3d7141d07)
夢を叶えるインターフェイス

**無駄に**未来感があるインターフェイスを作ってみました。
![ntxbi-8qwsl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/1dcc11d6-a090-6be9-9143-b909751106ed.gif)

※こちらは[ディープラーニングガジェット](https://connpass.com/event/129065/)品評会のネタです。

#やりたかったこと
+ 映画「マイノリティリポート」に出てくる[格好いいやつ](https://www.youtube.com/watch?v=prfzRmrWlm4)を作りたかった
+ タッチパネルが使えない状況（手が汚れている等）でも使用可能なインターフェイスを作りたかった

#結果

まずは、結果をご覧ください。

+ キャプチャ範囲の設定（両手を使います。）
![j7972-ppr28.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/c1a9cacd-d3ba-a0a0-5abe-d2d75a18d0ef.gif)

+ キャプチャ画像の移動・拡大
![ntxbi-8qwsl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/1dcc11d6-a090-6be9-9143-b909751106ed.gif)

#環境
+ Raspberry Pi 3
+ USB camera
+ NCS2

#実はクソアプリ
このアプリ、全く使い物に立ちません。その理由は以下のとおりです。

+ もっと便利な[商品](https://goodpatch.com/blog/leap-motion/)がある
+ ハード代が高価（3万円弱）
+ 使うと腕が疲れる

#アルゴリズム
アルゴリズムは簡単です。

まず、[handtracking-OpenVINO](https://qiita.com/shinmura0/items/07d976fc13ce774036b8)を使って、手を検出します。
そして、検出した手が閉じていると、「入力あり」と見なしています。

![ありなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/b77ce4b4-fe91-8727-0708-15a6e3d7de30.png)

手の開閉は、手の検出枠（バウンディングボックス）の「縦横比」で判定しています。
縦長（手が開いている）であれば「入力なし」、それ以外であれば「入力あり」と判定しています。

ただ、縦横比をはっきりさせるために、**親指を曲げて**手を開いています。
お釈迦様のような手にしないといけません。

また、手のひらをカメラに向けると、手が二つあるように認識してしまい、
うまく判定ができません。

![へい.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/d8216725-02e7-d3ff-fa37-9a05dacf8038.png)

従って、手の甲をカメラに向けています。

#改善に向けて
今のところ、完成度が低いため、コードは公開しませんが、改善できたら
公開しようと思います。

少しでもクソアプリから脱却すべく、以下の項目を改善したいです。

##手の認識
前述したように、手の動作に制約があります。

制約を無くすためには、[DOC](https://qiita.com/shinmura0/items/7f4298b75d6b788bba80)や[TripletLoss](https://qiita.com/koshian2/items/b4c4ffda99c07a1ac6b8)を使うと、[高速](https://qiita.com/PINTO/items/7782ed94a59f79ae8a69)にかつ正確に
手の開閉を認識できるようになります。

親指を曲げて手を開く必要もないですし、手の甲を見せる必要もなくなるでしょう。

##価格について
現状はハード代が高価です。

ハードを[Jetson Nano](https://qiita.com/karaage0703/items/b14c249aa33112669ee4)に代えると、価格を一万円強に抑えることができます。
スピードは未知数ですが、10FPSくらいにはなると思います。

#最後に

[handtracking](https://github.com/victordibia/handtracking)は、元々**普通のPC**で動くように開発されたものです。(CPUで10FPS)

従って、元のリポジトリを改造すれば、普通のPCでもこのアプリを動かすことができます。
やってみたいという方がいましたら、チャレンジしてみてください！
axiosのinterceptorsで、リクエストの前処理を共通して行う

[axios](https://github.com/axios/axios)を使ってAPIリクエストを送る際に、前処理を行いたいケースがありました。
リクエストを送る前に毎回処理を記載する方法もあるのですが、interceptorsを使用することで綺麗に書けそうだったので調べてみました。

## [interceptors]((https://github.com/axios/axios#interceptors))とは
interceptは途中で捕まえるといった意味のようです。
> You can intercept requests or responses before they are handled by then or catch.

### リクエストを送る前にログを出してみる
interceptorsを使用して、毎回リクエストとレスポンスの前にログを出力させてみます。

```javascript
import axios from 'axios';

axios.interceptors.request.use(request => {
  console.log(request.url)
  return request
})

axios.interceptors.response.use(response => {
  console.log(response.url)
  return response
})


axios.post('/path')
.then(() => {
  console.log('ok')
})
.catch(() => {
  console.log('ng')
})

// /path
// 200
// ok
```

下記の順番で出力されていることがわかりました。
1. interceptors.requestのログ
2. interceptors.responseのログ
3. then()のログ

### 実際にはパラメータやパスなどに処理を加える
実際に使う場合には、このようにリクエストを送る前処理を共通化させる場合などに使えると思います。

```javascript
axios.interceptors.request.use(request => {
  JSON.stringify(request.data)
  return request
})
```