OmniAICreator/Qiita-1.07M huggingface dataset:
[iOS/Swift] アプリ開発の実務的アプローチで学ぶデザインパターン ～Observer～

この記事シリーズは、iOS/Swiftエンジニアである執筆者個人が、
**ごく普通のiOSアプリ開発でよくある状況**や
**Swiftのコアライブラリやフレームワークで使われているパターン**に
着目してデザインパターンを学び直してみた記録です。

**関連記事一覧**
[[iOS/Swift] アプリ開発の実務的アプローチで学ぶデザインパターン](https://qiita.com/y-some/items/96db5f24ded4a1fab48f)

# Observerパターン概要

- Observerとは「観察者」という意味です。
- **オブジェクトの状態が変化した際に、そのオブジェクト自身が、「観察者」に状態の変化を「通知」する仕組みです。**
- GoFのデザインパターンでは**振る舞いに関するパターン**に分類されます。
- iOSアプリ開発では、他のどのパターンよりも実用的なパターンと思います。

# 使い所

実務においては、ViewControllerにAPI通信やデータ取得/更新などのロジックを詰め込むとViewControllerが肥大化してしまい、保守性が低下します。

そこで例えば、API通信やデータ取得/更新をViewModelに追い出す「MVVMアーキテクチャー」などを導入したりします。
**ViewModelからViewControllerに状態変化の通知をする**際にObserverパターンを良く使います。

# サンプルコード

Xcode 11.3 / Swift 5.1 です。

```swift
import UIKit

// MARK: - Imageの変化を通知するためのprotocol
protocol ImageObserver: class {
    func didChange()
}

// MARK: - ViewModel
final class ViewModel {
    weak var imageObserver: ImageObserver?

    var image: UIImage? {
        didSet {
            // 値が変わったらObserverに通知
            if image != oldValue {
                imageObserver?.didChange()
            }
        }
    }

    /// サーバーから画像を取得する
    func requestImage(with url: URL) {
        URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in
            if let error = error {
                print("画像取得失敗: ", error)
                return
            }
            guard let data = data, let image = UIImage(data: data) else {
                return
            }
            self?.image = image // image.didSetが実行され、ViewController.didChange()に通知される
        }.resume()
    }
}

// MARK: - ViewController
class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!

    private let viewModel = ViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel.imageObserver = self
        let imageUrl = URL(string: "https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg")!
        viewModel.requestImage(with: imageUrl)
    }
}

// ViewControllerをImageObserver protocolに準拠
extension ViewController: ImageObserver {
    func didChange() {
        DispatchQueue.main.async { [weak self] in
            self?.imageView.image = self?.viewModel.image
        }
    }
}
```

# 補足

## Property Observers

`didSet`はプロパティに値がセットされた後に呼ばれる処理ブロックで、Property Observers（プロパティ・オブザーバー）と呼びます。
`oldValue`という予約された変数によって、以前値を取得できます。

プロパティ・オブザーバーには、値がセットされる前に呼ばれる`willSet(_:)`もあります。
こちらは引数で新しい値を取得できます。

プロパティ・オブザーバーがあることで、**上のサンプルコードで仮に`ViewModel.image`をセットする箇所が増えたとしても、 `imageObserver.didChange()`の呼び出しを増やさずに済みます。**

SwiftはObserverパターンを実装しやすい言語であると思います。

（参考リンク）
[The Swift Programming Language - Properties](https://docs.swift.org/swift-book/LanguageGuide/Properties.html)

## Observerパターン以外の通知方法

iOS/Swiftにおいては、Observerパターン以外にもオブジェクト間の通知の方法がいくつかあります。

こちらの記事が参考になります。
[Swiftとオブジェクト間の通知のパターン](https://qiita.com/shtnkgm/items/f07f1c61985214ceb7b3)
ベールのカテゴリー定理

ベールのカテゴリー定理関連のノート．
ベール空間を定義し，ベールのカテゴリー定理を証明．
その応用として，
- 一様有界性定理,
- 開写像定理， 
- 逆写像定理，
- 閉グラフ定理の証明．
選択公理の使用箇所を明示している．
![Baire_image1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577582/d5576852-f2f7-2083-c61f-9eb4d62d185a.jpeg)
![Baire_image2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577582/2bde8c01-66ee-9b6f-33ce-d96a77f771ba.jpeg)
![Baire_image3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577582/9b16bae2-6bc6-40e4-685f-82c0bfb46aa0.jpeg)

↓pdfはこちらから．
 
<BLOCKQUOTE CLASS="twitter-tweet"><A HREF="https://twitter.com/YamagataTwit/status/1223580367153594373">ベールのカテゴリー定理</A></BLOCKQUOTE>
Rustの「Ord」、「PartialOrd」とは(初歩)

## おことわり

筆者は数学的知見に乏しく、専門的な解説としては不備があります。
数学的解説としてではなく、意味の把握程度に目を通して頂ければ幸いです

# 概要
**Ord** は**全順序集合**(Total Order)、
**PartialOrd** は**半順序集合**(Partial Order)を指しています。

数学的な証明は置いといて、ざっくり何が違うのかと言うと

・任意の要素 **全て** が **比較可能** であるか(Ord)
・**比較不可能か** (Partial_Ord)

といった違いが存在します
以下で実際のソースを見てみましょう

# 例
Ordトレイトを実装している **i32** と
PartialOrdトレイトしか実装されていない **f64** にて例を示してみます。

```rust
// i32の場合
fn main(){
    let val:i32 = 15;
    let v = vec![15,32,22,35,92,0];

    //どんな要素を選んでも比較可能
    println!("{},{},{}",val<=15,val>=15,val<=std::i32::MAX);

    //Ordが実装されているので、Iterator::max()等も使える
    println!("{}",v.iter().max().unwrap());
    
}
```

一方、f64になると

```rust
fn main(){
    let val:f64 = 1.2;
    let v:Vec<f64> = vec![15.0,32.0,22.0,35.0,92.0,0.0];

    //表現可能な数値は比較可能だが…
    println!("{},{},{}",val<=5.3,val>=2.4,val<=std::f64::MAX);

    //NANとの正しい比較が行えない
    println!("{},{},{}",val<=std::f64::NAN,val>=std::f64::NAN,val==std::f64::NAN);

    //Ordが実装されていないので、Iterator::max()等は使えない
    //println!("{}",v.iter().max().unwrap());

}
```

となり、f64では**NAN**との**正しい比較**が不可能なためOrdの要件を満たせなくなります。
このように、比較不可能な要素が存在するorしないが
**PartialOrd**と**Ord**の主な違いです

#最後に

(大切な事なので)もう一度言うと
・**Ord** は、どのような要素を選んでも **比較可能** な型に
・**PartialOrd**は、**比較不可能** な要素が存在する型に
実装されています

#参考
・[Rustで競技プログラミング スターターキット](https://qiita.com/hatoo@github/items/fa14ad36a1b568d14f3e)(@hatoo@githubさん)
　→PartialOrdの解説と、NANを受け取った時に**パニック**を起こす**Ordトレイトラッパ**の実装が紹介されています。

・[Rustでf32やf64の配列の最大値を得る方法](https://qiita.com/lo48576/items/343ca40a03c3b86b67cb)(@lo48576さん)
　→f32/64配列の**最大値**を取得する方法が解説されています。

どちらの記事も非常に参考になる内容でしたので、是非一読されることを
オススメします
micro:bitでコンパス

#micro:bitの磁気センサー
磁気センサーを使うと向いている方角を調べられるので、大まかに向いている方向をN,E,S,Wで表示するコンパスを作る。

##プログラム
向いている方角が0〜359で取得できるので、それを0から3の数字に変換して、0なら"N",1なら"E",2なら"S",3なら"W"と表示する。
![2020-02-01-192703_898x623_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576327/582171ea-b99b-7038-bf56-17e81f9b5efa.png)

##実行
動かしてみるとこんな感じで、向いてる方向に合わせて表示されるようになった。
![compass.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576327/c4ac83cf-92ee-924e-32f6-94d1b52db0af.gif)
ふわっとフェードイン


[参考サイト：というかここの内容です]（https://web-loid.net/web/scroll-effect-js/）

##
```html
<div class="scroll-fade">
    この要素がフェードします。
</div>
```

```javascript:jQuery
$(function(){
  var effect_pos = 300; // 画面下からどの位置でフェードさせるか(px)
  var effect_move = 50; // どのぐらい要素を動かすか(px)
  var effect_time = 700; // エフェクトの時間(ms) 1秒なら1000

  // フェードする前のcssを定義
  $('.scroll-fade').css({
      opacity: 0,
      transform: 'translateY('+ effect_move +'px)',
      transition: effect_time + 'ms'
  });
  // スクロールまたはロードするたびに実行
  $(window).on('scroll load', function(){
    $('.scroll-fade').each(function(){
        var targetElement = $(this).offset().top;
        var scroll = $(window).scrollTop();
        var windowHeight = $(window).height();
        if (scroll > targetElement - windowHeight + effect_pos){
          $(this).css('opacity','1');
          $(this).css('transform','translateY(0)');
        }
    });
  });
});

```


## 連続でフェードイン

```html

<div class="ex1 scroll-fade-row">
    <div><span>1</span></div>
    <div><span>2</span></div>
    <div><span>3</span></div>
    <div><span>4</span></div>
    <div><span>5</span></div>
</div>
```
```css:css
.ex1 {
    display: flex;
    justify-content: space-between;
}
.ex1 div {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100px;
    height: 100px;
    background-color: #e45151;
}
```
```javascript:jQuery$(function(){

    var effect_btm = 300; // 画面下からどの位置でフェードさせるか(px)
    var effect_move = 50; // どのぐらい要素を動かすか(px)
    var effect_time = 800; // エフェクトの時間(ms) 1秒なら1000

    //親要素と子要素のcssを定義
    $('.scroll-fade-row').css({
        opacity: 0
    });
    $('.scroll-fade-row').children().each(function(){
        $(this).css({
            opacity: 0,
            transform: 'translateY('+ effect_move +'px)',
            transition: effect_time + 'ms'
        });
    });

    // スクロールまたはロードするたびに実行
    $(window).on('scroll load', function(){
        var scroll_top = $(this).scrollTop();
        var scroll_btm = scroll_top + $(this).height();
        var effect_pos = scroll_btm - effect_btm;

        //エフェクトが発動したとき、子要素をずらしてフェードさせる
        $('.scroll-fade-row').each( function() {
            var this_pos = $(this).offset().top;
            if ( effect_pos > this_pos ) {
                $(this).css({
                    opacity: 1,
                    transform: 'translateY(0)'
                });
                $(this).children().each(function(i){
                    $(this).delay(100 + i*200).queue(function(){
                        $(this).css({
                            opacity: 1,
                            transform: 'translateY(0)'
                        }).dequeue();
                    });
                });
            }
        });
    });

});
```
form_forの自分がよくわからない所をまとめる

form_forのhamlの書き方について書いていきます。

```haml

.form
  = form_for [@group, @message] do |f|
    = f.text_field :content, class: 'form__message', placeholder: 'type a message'
    .form__mask
      = f.label :image, class: 'form__mask__image' do
        = icon('fas', 'image', class: 'icon')
        = f.file_field :image, class: 'hidden'
    = f.submit 'Send', class: 'form__submit'
```
form_forのクラス名(ビューが親をflexにすることによって崩れた時など)

```haml

= form_for [@group, @message], html: { class: "foo" }
```

fにクラスをつける

```haml

= f.submit "送る", class: "submit-btn"
```
viエディター

#viエディタにて:wq!コマンドで編集したパスを保存する時に怒られた場合
```:w !sudo tee %```
上記のコマンドを実行した後にパスワードを入力する。

#編集する場合
iと入力する。

#編集したものを保存して終了する
:wq
初心者によるプログラミング学習ログ 227日目

100日チャレンジの227日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

227日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>227日目<br>・架空のwebサイトコーディング<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1223705243948478464?ref_src=twsrc%5Etfw">February 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
JavaScriptで再開可能なアップロード


JavaScriptで再開可能なアップロードを実現するには、どうしたらいいのだろうか？

ブラウザ側ではファイルがどれだけアップロードされたか分からない。
なので、サーバーに問い合わせる必要がある。問い合わせるためには、ファイルのIDが必要。
アップロード時はファイルIDを常にサーバに送信しておく。

```js:ファイルIDの生成例
const fileID = encodeURIComponent(file.name + '-' + file.size + '-' + file.lastModifiedDate)
```

サーバに問い合わせて中断ファイルサイズ(startByte)が取得できたら、ファイルIDと開始バイトをヘッダに付与してアップロード。ファイルの切り出しには、File(Blob)オブジェクトのsliceメソッドを利用する。

```js:ヘッダと本体の送信
xhr.setRequestHeader('X-File-ID', fileID)
xhr.setRequestHeader('X-File-Start', startByte)
xhr.send(file.slice(startByte))
```


(参考)再開可能なファイルアップロード
https://ja.javascript.info/resume-upload
AWS CLIでフィルターをかける方法（filtersオプション）

# はじめに

[Elasticacheのチュートリアル](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/services-elasticache-tutorial.html)をやっている時に、コマンドの引数で「デフォルトのセキュリティグループのIDを指定する」という部分があったので、コマンドで楽に拾う方法がないかと思い、CLIを少し調べました。

差し当たり、--queryの方は敷居が高そうだったので--filtersの方を調べました。

# 環境情報

OS : Windows10
CLI : aws-cli/1.17.9 Python/3.7.4 Windows/10 botocore/1.14.9


# 構文

今回は「デフォルトのセキュリティグループのID」が欲しかったので、グループ名が「default」のものを検索しました。

    aws ec2 describe-security-groups --filters "Name=group-name,Values=default"

- 書式 : --filters "Name=`(name)`,Values=`(value)`"

※注意点
① 大文字と小文字は区別される（"name="のように書くと構文エラーになる）
② Name=で指定する名前はコマンド出力結果と異なる

例えば、下記情報をfiltersで取得したい場合。

    {
        "SecurityGroups": [
            {
                "Description": "default VPC security group",
                "GroupName": "default",
                "IpPermissions": [
                    {
    
この場合で、グループ名で検索したいからといって「Name=GroupName」と書いてもエラーになります。
これはコマンドの出力される時の名前と内部で管理している名前が異なるためです。

    > aws ec2 describe-security-groups --filters "Name=GroupName,Values=default"

    An error occurred (InvalidParameterValue) when calling the DescribeSecurityGroups operation: The filter 'GroupName' is invalid

--filtersでどのリソース名を指定すれば良いかは、コマンドに「help」を付けると確認することができます。

    > aws ec2 describe-security-groups help
    
    （省略）
    Options
    *******
    
    （省略）
    "--filters" (list)
    
       The filters. If using multiple filters for rules, the results
       include security groups for which any combination of rules - not
       necessarily a single rule - match all filters.
    （省略）
    
       * "group-name" - The name of the security group.
     
    （以下省略）

# 補足

--filtersでAND検索をする場合は、"Name～Values～"のセットを空白区切りでもう一つ追加します。
（その際、条件セット毎に""で括ってあげないとうまく拾えないので注意）

    aws ec2 describe-security-groups --filters "Name=group-name,Values=default" "Name=vpc-id,Values=vpc-a43d6fc3"

OR検索をする場合は、キー（Values）の部分にカンマ（,）で追加します。

    aws ec2 describe-security-groups --filters "Name=group-name,Values=default,launch-wizard-9"
    
尚、別々のキーをOR検索したい場合はそのままではできないので、複数回コマンドを実行した上で結果をマージする、という作業が必要になるそうです。


# 参考URL

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-output.html

https://www.karakaram.com/aws-cli-filters-usage

https://dev.classmethod.jp/cloud/aws/aws-cli-filter-and-query-howto/
ssh接続する際にTerminalの色を変える（Ubuntu版）

## はじめに

人間は必ずミスを犯すものです。
少しでもミスを減らす為、出来ることはしましょう。
他にいい案があれば教えていただけると嬉しいです。
（macOS版は[こちら](https://qiita.com/kanchi/items/c449216212febb857f29)）

## 環境

Ubuntuにデフォルトで入っているTerminal

## スクリプト

少しでもミスを減らしたいのでaliasでコマンドを置き換えるなどせず、環境毎にスクリプトを作成するのがいいと思っているのでそれ用のスクリプトです。
適時自分の環境に書き換えてください。

```ssh_color_change_ubuntu.sh
#!/bin/bash

# ssh connection script for ubuntu

################################################
# style guide
# http://google.github.io/styleguide/shell.xml
################################################

# colors list
white="#ffffff"
sky_blue="#00ccff"
red="#ff4b00"
default="#300a24" # default ubuntu back color

################################################
# color change function
# Globals:
#   None
# Arguments:
#   1:word color
#   2:back color
# Returns:
#   None
################################################
function color_change() {
  word=$1
  back=$2
  echo -ne "\e]10;${word}\a\e]11;${back}\a"
}

# Ctr-c processing
# default terminal color
trap "color_change \"${white}\" \"${default}\"" 2

color_change "${white}" "${red}"

# command
ssh username@hostname

# end
color_change "${white}" "${default}"
exit 0
```
シェルでつくる画像形式変換プログラム

シェルの勉強と作業効率化を兼ねてつくりました。
覚えるの大変そうですね...

#　jpegをepsに変換  

```bash:cvt_jpeg.sh

#! /bin/bash

for f in *.jpeg; do
	convert $f eps2:${f%.jpeg}.eps;
done
```
最近のvm.swappiness @CentOS7以降

[CentOS7再起動でsysctlで設定したカーネルパラメータが反映されないのはTunedが原因だった](https://yomon.hatenablog.com/entry/2016/08/19/224217)


RedHat公式文書
[3.2. tuned と tuned-adm によるパフォーマンスチューニング Red Hat Enterprise Linux 7](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/performance_tuning_guide/sect-red_hat_enterprise_linux-performance_tuning_guide-performance_monitoring_tools-tuned_and_tuned_adm)

[【memo】CentSO7 チューニング機能 - Qiita](https://qiita.com/moukuto/items/df90f314058c3c56a4ac)
シェルでgnuplotのグラフを一括plotしてみた

# はじめに  
こんにちは！Qiita初投稿です。
大学の授業のOpenCVの課題提出で出力画像のヒストグラムをgnuplotで毎回変換しなければならず鬱になっていました。

そこで、シェルスクリプトを使ってディレクトリ内にある**すべてのtxtファイルをepsに変換してplot**するプログラムをつくりました。

# やったこと

* シェルスクリプトのお勉強

### フォルダ内のtxtファイルをすべてgnuplotでplot　
ググりながら作りました。プログラムの先頭に#/bin/shは必ずいるようです。

### 
```test.sh
#!/bin/sh

for f in *.txt;
do
gnuplot<<EOF
#gnuplotでのx軸の設定値
set xrange [0:256]
set xtics 0, 64, 256

#txtをplotデータに変換
plot "$f" with boxes
set terminal postscript eps
set output "${f%.txt}.eps"
replot
quit
EOF
done
```
「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.9 文字列の回転


「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.9 文字列の回転

#目次
###CHAP1. 配列と文字列
1. [重複のない文字列](https://qiita.com/YusukeEngineer/items/494ccb49de66b39d16c0)
2. [同じ文字の数を数える](https://qiita.com/YusukeEngineer/items/4ed19c5f6efa23c62351)
3. [URLify](https://qiita.com/YusukeEngineer/items/4208561f8e1ac04cbbf4)
4. [回文の順列](https://qiita.com/YusukeEngineer/items/5d05620f3d9e9cc4e7b5)
5. [一発変換](https://qiita.com/YusukeEngineer/items/122360b8a95f6eb858f7)
6. [文字列圧縮](https://qiita.com/YusukeEngineer/items/0bd139a361ce3f4eac36)
7. [行列の回転](https://qiita.com/YusukeEngineer/items/4b2fd1ed64385612cba6)
8. ["0"の行列](https://qiita.com/YusukeEngineer/items/bed1ce30d4ef966fe142)
9. [文字列の回転](https://qiita.com/YusukeEngineer/items/2b6f9d2a733d2815a1ac)

#Pythonコード解答例
```python
def isSubstring(s1,s2):

    return s2 in s1

def isRotation(s1,s2):

    length = len(s1)

    if length==len(s2) and length>0:
        s1s1 = s1 + s1  
        return isSubstring(s1s1,s2)

    return False

input_str_1 = "waterbottle"
input_str_2 = "bottlewater"

print(isRotation(input_str_1,input_str_2))

input_str_3 = "waterbottle"
input_str_4 = "water"

print(isRotation(input_str_3,input_str_4))
```
Hugo - Dapper スピード勝負


# Summary

perlで書かれた小さな静的サイトジェネレーター[Dapper](https://github.com/markdbenson/dapper)は実用に耐えるのか。ある程度の規模のサイト運営を視野に、サイト構築にかかる所要時間をチェックしてみた。

[Dapper](https://github.com/markdbenson/dapper)は競合他ソフトに比べて必ずしも不利というわけではない。しかし、評判の高いHugoに比べるとかなり遅いとの結果が得られた。快適なサイト運営を実現するにあたっては、データ管理に何らかの工夫が必要かもしれない。

# Introduction

[Dapper](https://github.com/markdbenson/dapper)は、別記事『[perlベースの静的CMS : Dapperを試してみませんか？](https://qiita.com/doikoji/items/fa7793aaab0224c31e7e)』にて紹介したとおり、シンプルでわかりやすく使いやすそうな静的サイトジェネレーターである[^1]。

2020年2月初頭現在、私はこのDapperが本格的に自サイトの運営に使えるか検討中なのだが、その過程で、『[多量のページを扱う場合の静的サイトジェネレータのパフォーマンス](https://qiita.com/tnzk/items/4863e2c559f6b71b72e0)』という記事を発見した。

確かに性能評価は必要だ。一見使いやすそうでも、対象サイトの規模がちょっと大きくなると手も足も出なくなってしまうというのでは困る。この記事に触発されて、dapperの簡易的な性能テストとして「1000記事からなるサイトの構築にどれぐらい時間を要するか」を試してみることにした。

私の事前の予想（期待）は、次のようなものであった。

> いうてもテキスト処理を得意とするperlベースのシステムだからね。他の同類ソフトと比べて結構いい勝負をしてくれるのではないか。

# Material and Method

今回は、記事ソースに見立てた1000個のmarkdownファイルを用意し、これを、Dapperにかけてサイト構築、すなわちHTMLファイルの生成をやらせる。他方、爆速な静的サイトジェネレーターとの評価が高いHugoにも同じデータを処理させる。両者の所要時間を比較し、Dapperの有用性について検討する。

## データの準備
まずは処理の対象となるソースファイルとして、前述の参考記事の中でも使われていたhttps://gist.githubusercontent.com/DominikAngerer/b4a29b5ec9a69fc09546882586bc2d6b/raw/aeab6fdd6dbbcb7626e2ef2a8123e677cc19dcc1/lorem-markdown.md
をダウンロードした。

Dapper用として、このmdファイルにFront Matter（サイト名・およびレイアウトファイル名を指定した2行のパラメータ設定）を付加した上で1000コピー作って、Dapperのソースファイル用ディレクトリ中に配置した。

次に、Hugo用として、同じmdファイルを1000コピー作って「コンテンツ用ディレクトリ」に配置した。

## サイト作成
それぞれのテスト用ディレクトリの中でtimeコマンドを通してサイト構築用コマンドを実行し、htmlファイル群を生成させ、所要時間をチェックした。

## 使用したソフトのバージョン

検証に使用した両ソフトのバージョンは以下の通りだ。

* Hugo Static Site Generator v0.63.0-DEV linux/amd64 BuildDate: unknown
* Dapper version 0.18

# Result

それぞれのサイト構築コマンドの実行結果を示す。

## hugoの場合

```
$ /usr/local/time -p hugo
中略
Total in 2587 ms
real 2.63
user 4.75
sys 0.38
```

## dapperの場合

```
$ /usr/local/time -p dapper build
中略
Project built.
real 23.42
user 23.05
sys 0.35
```

# Discussion

[参考にさせてもらった記事](https://qiita.com/tnzk/items/4863e2c559f6b71b72e0#%E6%A4%9C%E8%A8%BC%E7%B5%90%E6%9E%9C)では、同等規模のサイト構築にHugoで1.726秒かかったということなので、私のマシンはその70%の処理能力ということか。

当該参考記事での試験結果から単純計算を試みれば、おそらくDapper君はGatsByやVuePressには勝てる可能性が高そうだ。決して悪いパフォーマンスではない。しかしながら、私の実験ではHugoに比べるとDapperのサイト構築には10倍の時間がかかった…。予想以上の差での敗北。いやHugoの評判は伊達ではなかったというところか。

1000ファイルからなるサイトは決して現実的に大規模とはいえない。ブログを毎日地道に継続執筆していけば、3年弱でこれぐらいの規模には確実に到達するわけだ。サイトデータ更新に20秒強かかるとなると、寝る前に一回だけ実行とかであればよいが、試行錯誤・推敲を繰り返しながらその日のうちに何度も構築をかけるというスタイルで臨むにはいささかストレスが溜まる待ち時間と言わねばならないだろう。

もちろん、所属組織のちょっとした紹介サイト[^2]を作りたいといった要請であれば、dapperの処理速度は全く問題にはならず、充分に速く処理を済ませてくれると言ってよいだろう。その上、余計なものが出来ない分かえってコンテンツの管理がしやすく、テキストはmarkdownを利用してちゃっちゃと揃えることができる。そうした点で、dapperは誠に間尺にあった選択となりえる。

しかし、大規模なサイトを相手にするならば、再構築にかける必要のないソースファイルはbuild前に別所に退避しておくなどの対応を考えるべきかもしれない。もちろん、build→アップロードを実行するシェルスクリプトを作っておき、それを呼び出したら結果を待たずに寝てしまうというのも一つの対処ではあるだろうが。

[^1]: なお、ググるとたくさんヒットする同名のO/Rマッパーソフトとは関係ない。

[^2]: トップページに業務案内にスタッフ紹介などを含めて全部で数十ページかそこらからなる古典的な「ホームページ」を想定
「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.8 "0"の行列


「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.8 "0"の行列

#目次
###CHAP1. 配列と文字列
1. [重複のない文字列](https://qiita.com/YusukeEngineer/items/494ccb49de66b39d16c0)
2. [同じ文字の数を数える](https://qiita.com/YusukeEngineer/items/4ed19c5f6efa23c62351)
3. [URLify](https://qiita.com/YusukeEngineer/items/4208561f8e1ac04cbbf4)
4. [回文の順列](https://qiita.com/YusukeEngineer/items/5d05620f3d9e9cc4e7b5)
5. [一発変換](https://qiita.com/YusukeEngineer/items/122360b8a95f6eb858f7)
6. [文字列圧縮](https://qiita.com/YusukeEngineer/items/0bd139a361ce3f4eac36)
7. [行列の回転](https://qiita.com/YusukeEngineer/items/4b2fd1ed64385612cba6)
8. ["0"の行列](https://qiita.com/YusukeEngineer/items/bed1ce30d4ef966fe142)
9. [文字列の回転](https://qiita.com/YusukeEngineer/items/2b6f9d2a733d2815a1ac)

#Pythonコード解答例
```python

import numpy as np

def setZeros(matrix):

    row = [False] * matrix.shape[0]
    column = [False] * matrix.shape[1]

    for i in range(matrix.shape[0]):
        for j in range(matrix.shape[1]):
            if matrix[i,j] == 0:
                row[i] = True
                column[j] = True

    for i in range(len(row)):
        if row[i]:
            nullifyRow(matrix,i)

    for j in range(len(column)):
        if column[j]:
            nullifyColumn(matrix,j)

def nullifyRow(matrix, row):

    for j in range(matrix.shape[1]):
        matrix[row,j] = 0

def nullifyColumn(matrix, col):

    for i in range(matrix.shape[0]):
        matrix[i,col] = 0


input_matrix_1 = np.matrix([[1,2,3,4],[5,6,0,8],[9,10,11,12],[13,14,15,16]])

print(input_matrix_1)

setZeros(input_matrix_1)

print(input_matrix_1)

input_matrix_2 = np.matrix([[0,2,3,4],[5,6,7,8],[9,10,11,12],[0,14,15,16]])

print(input_matrix_2)

setZeros(input_matrix_2)

print(input_matrix_2)
```
Gitコマンド備忘録

コマンドを思い出すためのメモ

### ローカルリポジトリの作成
    git init // .gitディレクトリが作成される
### Gitリポジトリのコピーをローカルに作成する
    git clone <リポジトリ名>
### 変更をステージに追加する
    git add <ファイル名>
    git add <ディレクトリ名>
    git add .
### 変更を記録する
    git commit
    git commit -m "<コミットメッセージ>" <ファイル名> // コミットメッセージを入力してコミット
    git commit -v <ファイル名> // 変更点を表示してコミット
### 現在の変更状況を確認する
    git status  // 変更されたファイルを確認
### 変更差分を確認する
    git diff <ファイル名>
    git diff --staged // git addしたあとの変更差分
### 変更履歴を確認する
    git log
    git log --oneline // 一行で表示する
    git log -p <ファイル名> // ファイルの変更差分を表示する
    git log -n <コミット数> // 表示するコミット数を制限する
### ファイルごと削除
    git rm <ファイル名>  // リポジトリ、ローカル共にファイルを削除
    git rm --cached <ファイル名> // ファイルを残したいとき
### リモートリポジトリを新規追加する
    git remote add origin https://github.com/user/<リモートリポジトリ名>.git
### ローカルリポジトリをリモートリポジトリにpushする
    git push <リモート名> <ブランチ名>
    git push origin master
### コマンドにエイリアスをつける
    // 「ci」 と入力すると 「commit」 が実行される
    git config --global alias.ci commit
     // 「st」 と入力すると 「status」 コマンドが実行される
    git config --global alias.st status
### ステージした変更を取り消す
    git reset HEAD <ファイル名>
    git reset HEAD <ディレクトリ名>
### 直前のコミットをやり直す
    git commit --amend // ※pushしたコミットはやり直さないこと
### リモートの情報を表示する
    git remote
    git remote -v
### リモートリポジトリを新規追加する
    git remote add <リモート名> <リモートURL>
【GAS】claspを使う - 基本的な操作紹介(Gitについても少し) - 

導入はこちらで書いてます。
⇒[【GAS】claspでソース管理できるようにする](https://qiita.com/wau/items/0b4ad172b01cdb4ec621)

## login
```
$ clasp login
```

## clone
```
$ clasp clone [スクリプトID]
```

スクリプトIDは

- GASプロジェクトのトップ画面のURLにあるID部分
- トリガー画面のURLにあるID部分

が該当します。（どちらも同じID）
GASコードでスプレッドシートをSpreadsheetApp.openById()で参照するときのIDと同じ感覚です。

これができたら対象プロジェクトのGASコードとというファイルができあがっているかと思います。

### .clasp.jsonについて
これがclaspのキモになる部分のようです。

```.clasp.json
{"scriptId":"スクリプトID"}
```

このスクリプトIDを使って、claspはpull/push先を振り分けられる仕組みになっているようです。

## pull
.clasp.jsonファイルのあるディレクトリで下記を実行すると、その.clasp.jsonで指定しているコードをpullできます。

```
$ clasp pull
```

## push
考え方はpullと同じ。

```
$ clasp push
```

ただはじめて実行する際に、以下のようなエラーが出ることがあります。

> User has not enabled the Apps Script API. Enable it by visiting https://script.google.com/home/usersettings then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

これは設定の問題なので、書いてある通り記載のURLにブラウザでアクセスして"Google Apps Script API"をONすればいけます。

## logout
```
$ clasp logout
```

## gitとの連携について
私はとりあえず以下のような感じでgit連携しようと思ってます。


```
─Git_Management_Dir
　　├ .git
　　├ README.md
　　├ Script_1
　　　　├ .clasp.json
　　　　└ sourceCode
　　└ Script_2
　　　　├ .clasp.json
　　　　└ sourceCode
```

Script_1にScript_2のコードが表示されるというようなことはありませんでした。
対応する.clasp.jsonがそれぞれにあれば変に干渉することは無さそうです。

っていうかgit管理するならコードに日本語とか入れなきゃ良かったと今更後悔……
「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.7 行列の回転


「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.7 行列の回転

#目次
###CHAP1. 配列と文字列
1. [重複のない文字列](https://qiita.com/YusukeEngineer/items/494ccb49de66b39d16c0)
2. [同じ文字の数を数える](https://qiita.com/YusukeEngineer/items/4ed19c5f6efa23c62351)
3. [URLify](https://qiita.com/YusukeEngineer/items/4208561f8e1ac04cbbf4)
4. [回文の順列](https://qiita.com/YusukeEngineer/items/5d05620f3d9e9cc4e7b5)
5. [一発変換](https://qiita.com/YusukeEngineer/items/122360b8a95f6eb858f7)
6. [文字列圧縮](https://qiita.com/YusukeEngineer/items/0bd139a361ce3f4eac36)
7. [行列の回転](https://qiita.com/YusukeEngineer/items/4b2fd1ed64385612cba6)
8. ["0"の行列](https://qiita.com/YusukeEngineer/items/bed1ce30d4ef966fe142)
9. [文字列の回転](https://qiita.com/YusukeEngineer/items/2b6f9d2a733d2815a1ac)

#Pythonコード解答例
```python

import numpy as np

def rotate(matrix):

    if matrix.ndim == 0 or matrix.shape[0] != matrix.shape[1]:
        return False

    n = matrix.shape[0]

    for layer in range(0,int(n/2)):

        first = layer
        last = n-1-layer

        for i in range(first,last):

            offset = i - first
            top = matrix[first,i]

            matrix[first,i] = matrix[last-offset,first]

            matrix[last-offset,first] = matrix[last,last-offset]

            matrix[last,last-offset] = matrix[i,last]

            matrix[i,last] = top

    return True

input_matrix_1 = np.matrix([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])

print(input_matrix_1)

print(rotate(input_matrix_1))

print(input_matrix_1)

input_matrix_2 = np.matrix([[1,2,3],[4,5,6],[7,8,9]])

print(input_matrix_2)

print(rotate(input_matrix_2))

print(input_matrix_2)

```
PostgreSQLの概念図（データベースクラスタ/データベース/スキーマ/テーブル）

# PostgreSQLの概念図

- 以前PostgreSQLの理解の為整理した概念図

<img width="1167" alt="スクリーンショット 2020-02-02 0.25.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142483/178cafb0-471d-8bb8-9743-74e4d9718014.png">
clangでlinux kernelを自己ビルド

clangでlinux kernelを自己ビルドします。やり方は[以前書いた](https://qiita.com/tekito2/items/64ced65ad2d23d78d96a)gccでビルドするのとほぼ同じです。clangは以前の投稿で[インストール](https://qiita.com/tekito2/items/0a534781631342f2a3a9)したものを使います。
## 環境

+ OS: ubuntu 16.04LTS
+ コンパイラ： clang (9.0.0)

## 準備
clangコマンドが使えるようにPATHを通しておきます。

```
% export PATH=(somewhere)/bin:$PATH
```

ソースを取得し、展開、パッチ当てを行います。

```
% wget https://kojipkgs.fedoraproject.org//packages/kernel/5.4.16/200.fc31/src/kernel-5.4.16-200
.fc31.src.rpm
% mkdir files
% cd files
% rpm2cpio ../kernel-5.4.16-200.fc31.src.rpm |cpio  -id
% tar Jxf  linux-5.4.tar.xz
% cd linux-5.4
% xz -dc ../patch-5.4.16.xz  | patch -p1
% for i in `ls ../*patch`;do;patch -p1 < $i;done
```
## ビルド
.configの雛形を取得し、make oldconfigします。

```
% cp ../kernel-x86_64-fedora.config .config
% yes "" | make CC=clang oldconfig
```
ここで、menuconfigを動かしてからビルドします。
「Kernel hacking -> Compile-time checks and compiler options -> Generate BTF typeinfo」のチェックを外します。

```
% make CC=clang menuconfig
% make -j12 CC=clang deb-pkg LOCALVERSION=-my KDEB_PKGVERSION=1
```
## インストール
```
% cd ..
% su
# dpkg -i linux-image-5.4.16-my_1_amd64.deb linux-headers-5.4.16-my_1_amd64.deb
```
## おまけ
再起動して新カーネルで起動すると、/var/log/kern.logに以下のような文言を確認できます。

```
Feb  1 19:08:49 localpc kernel: [    0.000000] Linux version 5.4.16-my (tekito2@my-desktop3) (clang version 9.0.0 (tags/RELEASE_900/final)) #1 SMP Sat Feb 1 18:20:36 JST 2020
```
パスワードがあっているのに、mysqlからアクセス拒否されたので直した

#vagrantでweb開発環境を構築中に。。。
##mysqlへログインできなかった
###エラーメッセージ
```
mysqladmin: connect to server at 'localhost' failed error:
'Access denied for user 'root'@'localhost' (using password: YES)'
```
###stack overflowに解決法が載ってました
>https://stackoverflow.com/questions/41645309/mysql-error-access-denied-for-user-rootlocalhost

どうやらパスワードを忘れてしまって再設定するときにも使えるらしい
「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.6 文字列圧縮

「世界で闘うプログラミング力を鍛える本」Pythonコード解答例 - 1.6 文字列圧縮

#目次
###CHAP1. 配列と文字列
1. [重複のない文字列](https://qiita.com/YusukeEngineer/items/494ccb49de66b39d16c0)
2. [同じ文字の数を数える](https://qiita.com/YusukeEngineer/items/4ed19c5f6efa23c62351)
3. [URLify](https://qiita.com/YusukeEngineer/items/4208561f8e1ac04cbbf4)
4. [回文の順列](https://qiita.com/YusukeEngineer/items/5d05620f3d9e9cc4e7b5)
5. [一発変換](https://qiita.com/YusukeEngineer/items/122360b8a95f6eb858f7)
6. [文字列圧縮](https://qiita.com/YusukeEngineer/items/0bd139a361ce3f4eac36)
7. [行列の回転](https://qiita.com/YusukeEngineer/items/4b2fd1ed64385612cba6)
8. ["0"の行列](https://qiita.com/YusukeEngineer/items/bed1ce30d4ef966fe142)
9. [文字列の回転](https://qiita.com/YusukeEngineer/items/2b6f9d2a733d2815a1ac)

#Pythonコード解答例
```python
def compressBad(input_str):

    compressedString = ""
    countConsecutive = 0

    for i in range(len(input_str)):

        countConsecutive = countConsecutive + 1

        if i+1 >= len(input_str) or input_str[i] != input_str[i+1]:

            compressedString = compressedString + input_str[i] + str(countConsecutive)
            countConsecutive = 0

    return compressedString if len(compressedString) < len(input_str) else input_str

input_str = "aabcccccaaa"

print(compressBad(input_str))
```
製造業のBOMについて

●はじめに
これまで金融関連の知識しかありませんでしたが、製造業の基幹システムPJにアサインされ、そこで学んだ製造業に関する事のメモとして記録を残します。（プログラムやSQLに直接関連する内容ではありません。）
今回、未経験の業界（これまで社内SEだったので）のシステム開発に携わり、プログラマー・システムエンジニア問わず技術的知見も然りまず、業務への理解が不足していると開発、運用、保守全てにおいて質の高い仕事は出来ないと思いました。また、当たり前ですが、担当する工程が上流に行けば行くほどその傾向は顕著に現れると思い、将来の為に書き留めます。

●BOMとは
BOMとは、製品を作るのに必要な部品を一覧にし、製品の製造に関する重要な情報について端的に示したものです。製造に必要となる部品表は、設計部門で作られ、生産部門へと引き渡されます。生産部門では部品表を生産管理に必要な形に整え、スケジュールに落とし込みます。

●BOMの分類
BOMは用途によって数種類に分類されます。


◆M-BOM
→製造部品表
製品の組立に必要な部品リストで表示します。製造（加工・組立・外注）に必要な部品・資材情報と工程順序情報を表し、生産スケジュールや生産指示、工程管理、部品手配（サプライヤーへの発注のタイミング）に活用されます。
◆E-BOM
→設計部品表
開発・設計段階で利用されます。部品やモジュールの使用、設計情報（図面データ）、技術情報などが表示され、部品やモジュールの詳細情報を提供します。
◆S-BOM
→販売部品表
販売支援で使用される販売部品表です。
◆他にも種類はありますがここでは割愛します。


●最後に
冒頭で述べたPJで関連のあったBOMは、主にM-BOMでした。最初は深く考える事なくスルーしてきたBOMですが、製造業を調べれば調べるほどなくてはならないモノだと思いました。
PJでは主に、データ移行を担当した為、各テーブルにBOMに関連する項目が多くある事も分かり、製造業にとって重要なモノなのだと実感した次第でした。
これからも、断片的なシステムだけでなく全体のアーキテクチャを意識する事に加えて、業務内容や業務フローに関する知識を習得しつつ業務に取り組んで行こうと思います。
Vue.js のキー修飾子を使う

# 概要 
本記事では、Vue.jsで用意されているキー修飾子の使用方法を紹介していきます。

## キー修飾子の種類
以下のキー修飾子が用意されている。
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right

## 実装方法
今回は、上記のうち`.enter`、`.space`を例にします。
指定したキーを押下した時に、関数を呼び出す事ができます。

```html:index.html
<div id="app">
  // エンターキーを押した時にアラートを表示
  <input type="text" v-on:keyup.enter="alert">
</div>
```

```js:index.js
new Vue({
  el: '#app',
  methods: {
    alert() {
      alert("アラート！");
    }
  }
})
```

キー修飾子は繋げて書くこともできる。

```html:index.html
<div id="app">
  // エンターキー、スペースキーを押した時にアラートを表示
  <input type="text" v-on:keyup.enter.space="alert">
</div>
```

```js:index.js
new Vue({
  el: '#app',
  methods: {
    alert() {
      alert("アラート！");
    }
  }
})
```
DeepLearning4Jのbeta6でUIServerが使えない問題の解決策

`DeepLearning4J`の`beta6`から`UIServer`周りも大きく変わっており、
例えば、mavenの指定は以下のように変更されています。

```xml:old_pom.xml
<dependency>
    <groupId>org.deeplearning4j</groupId>
    <artifactId>deeplearning4j-ui_2.1x</artifactId>
    <version>${dl4j.version}</version>
</dependency>
```
　↓

```xml:new_pom.xml
<dependency>
    <groupId>org.deeplearning4j</groupId>
    <artifactId>deeplearning4j-ui</artifactId>
    <version>${dl4j.version}</version>
</dependency>
```

しかし、こちらに変更後に今まで通り機械学習を開始しても
`http://localhost:9000/`から学習過程が見れない問題が発生しました。
具体的には、UIServerのWebサーバー自体が起動していないようです。

コンソールを見ても何もエラーや警告は出力されておらず、
ソースコードを読み解いて原因を解決してみました。

解決策は
pom.xmlに以下を追加するだけです。

```xml:new_pom.xml
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.29</version>
</dependency>
```
を指定するだけです。

原因としましては、単純にこの`UIServer`が対応しているバージョンが`2.3.29`だったから。
ではなぜわざわざ手動で設定しないと起動しないのか…
単純にbetaだからでしょう。
これ以外にも初歩的なミスがいくつか見られるので。
PowerShellでSBTの文字化けとjava.nio.charset.MalformedInputException: Input length = 1を倒す

開発で文字コード is UTF-8だと、WindowsはShift-JISなどが大好きなので文字化けする。

PowerShellを使っていると、文字コード周りでいつも爆死してしまう。。。


# sbt起動時や実行時の文字化け
JVMオプションで `-Dfile.encoding=UTF-8`を指定していても、sbtの起動時や実行時には文字化けしてしまった。

まず、PowerShell側のデフォルト文字コードはCP932なので、 `chcp 65001`コマンドで文字コードをUTF-8にしておく。

次に、この記事のようなことをする。

[MSYS2とsbtの設定](http://terurou.hateblo.jp/entry/2015/10/18/120657)

記事内で `build.sbt`に書く部分を `~/.sbt/1.0/global.sbt`に書いた。
（全てのプロジェクトに適用したくて）

やったか！？

---

余談

sbtの設定 (configとか)周りで色んな情報があったけど、僕の場合はどれもダメだった（別のケースではいけるかも）

[Windowsでsbt！@Git Bash](https://qiita.com/seri/items/702fcb15dffdc9395805)
[sbt 実行時に文字コードを UTF-8 に設定する](https://qiita.com/jacobiz/items/3fd54c5b697104904176)
[【解決済み】【Scala】WindowsでGit Bash利用時のsbt文字化け問題とその対策](https://seri.hatenablog.com/entry/2014/07/20/154734)





# java.nio.charset.MalformedInputException: Input length = 1
これも、文字コードが合わない時にエンカウントしがちなエラーっぽい。

Scalaでファイル読み込みの際に遭遇する（ `fromFile`でも `fromResource`でも）
[MalformedInputException when trying to read entire file](https://stackoverflow.com/questions/13327536/malformedinputexception-when-trying-to-read-entire-file)

どうやらシステム？のデフォルトエンコーディングを用いるらしく、多分WindowsだとデフォルトがUTF-8じゃないからお亡くなりになってそう。

["MalformedInputException: Input length = 1 " exception solution for Scala and Java](http://biercoff.com/malformedinputexception-input-length-1-exception-solution-for-scala-and-java/)

[How to read a text file with mixed encodings in Scala or Java?](https://stackoverflow.com/questions/13625024/how-to-read-a-text-file-with-mixed-encodings-in-scala-or-java)

上記で紹介されているように、ファイル読み込み処理で明示的に文字コード指定すれば良さそう。

他にも、

```scala
scala.io.Source.fromResource("v2okimochi_file_name")
```

と書いてMalformedInputExceptionだった場合は、

```scala
scala.io.Source.fromResource("v2okimochi_file_name")("UTF-8")
```

にすると良さそう。
Knowledge sharing for Windows

ゴッドモード発動
-------
フォルダ作成し、名前を以下に設定
GodeMode.{ED7BA470-8E54-465E-825C-99712043E01C}

HDD削除（Windows10標準機能）
-------
cipher /w:ドライブ名
ex) cipher /w:d:

フォーマットせずにNTFSへ変換
-------
convert ドライブ名 /fs:ntfs /v
ex) convert c: /fs:ntfs /v



To be continued....🌙🐰
grepとawkでblade内で多言語化の対象となる文字列を抽出する


bladeファイル内で、多言語対応の対象となっている文字列を抽出したいと思います。

```sh
grep -sr "__\((.*)\)" * | awk -F "__" '{print $2}' | awk -F "\(" '{print $2}' | awk -F "\)" '{print $1}' | grep -v "[a-Z]" > 翻訳候補.txt
```

blade内では

```
{{ __($textToBeTranslated) }}
```
という関数を介して描画すると文字列をキーに対応する言語に自動変換させることが出来ます。
なので、この関数に渡している文字列を抽出するような処理になりました。


##前提条件
Laravel 6.x

以上です。
Cassandra操作のGUIツール

#はじめに
分散に強いCassandraデータベースが利用する際に、GUIツールを使うと便利になります。

#Cassandraとは
http://cassandra.apache.org/

Manage massive amounts of data, fast, without losing sleep

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/acd9fa47-5005-d339-4d26-8b1b13a090f3.png)

出典：https://db-engines.com/en/ranking

#Cassandraの操作方法は？
##1. CQLでコマンド操作
SQL風にCRUDの操作は可能です。
CQL(Cassandra Query Language)：http://cassandra.apache.org/doc/latest/cql/index.html

##2.GUIツールで操作
###2.1 TablePlus
https://tableplus.com/
>Modern, native, and friendly GUI tool for relational databases: MySQL, PostgreSQL, SQLite

イメージ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/6820ce49-21b7-0f65-ec72-630cc1ec0052.png)

Free版は最大３つのタブしか開けない、フィルター機能は使えないなどの制限があります。

###2.2 datagrip
https://www.jetbrains.com/datagrip/
30日評価版があります。

###2.3 NoSQL Manager for Cassandra
https://www.mongodbmanager.com/cassandra/
30日評価版があります。

###2.4 cassandra-client
https://github.com/Kindrat/cassandra-client

###2.5 DataStax Studio (ブラウザで操作)
https://downloads.datastax.com/#studio

ただし、「Studio only supports DataStax Enterprise clusters. 」のため、OSSのCassandraサーバにはアクセスできません。
でも、DataStax社のドキュメントは豊富ですので、勉強になります。
https://docs.datastax.com/en/landing_page/doc/landing_page/cassandra.html

以上
CSV編集に使えないExcelから脱却する方法

#Microsoft製品に苦しめられる日々は終わった
Microsoft製品だからどんなものにでも使えるというのは幻想だ。
必ずしもそうとは限らない。むしろ、逆に使えるようにするために準備する手間が掛かったり、
内容によっては使えない場合があって苦しめられる。
バグらしき挙動もあるしMicrosoftだから安心という考えは捨てた方がいいかと思った。
やはり、全ての人のそれぞれの要求、用途に製品が応えるのは難しいと思ったし
その製品が持つ機能に対しても完全性を求めることは難しいことだと思った。 [^1]

## ExcelでCSVが編集しづらい、または編集できない問題点

### データの値が変換される
CSVはカンマ区切りで扱うデータという認識だが、CSVでは文字列扱いの数値もExcelでは勝手に変換されてしまう。
例：0099 → 99
対策としてはExcelで型を指定して取り込もうとすれば変換は起こらないが・・・。
（この作業が非常に手間でありメンドくさい。特定のソフトウェアで開くための作業は不毛であると思う。）
出来る限りCSVはプレーンな状態で扱いたいのが心情だ。[^2]


### データの中に改行が含むと改行される
データの中に改行が含むとExcelでは改行して表示するのだ。
たぶん、挙動としては合ってはいるのだが、レコードの様なデータとしては非常に扱いづらい。[^3]


## テキストエディタでも見づらい
テキストエディタはテキストの通り表示してくれるので安心はするのだが
同時に改行もされてしまうのでレコードの様なデータとして扱うときは
1レコードは1行で表示をしたいという気持ちからテキストエディタも向いていない。

### CSV編集に最適なツール
上記の問題を解決するツールがコレ。
個人的には今週のMVPである。[^4]

Edit csv

Visual Studio Code Extensions
https://marketplace.visualstudio.com/items?itemName=janisdd.vscode-edit-csv

github
https://github.com/janisdd/vscode-edit-csv

[^1]: 皆がMicrosoft製品を導入しているから、自分も導入するというようなお役所仕事は社会全体の活動、やりとりから見たときに仕方ない反面、何だかなと思うこともある。しかし、Microsoft製品が便利だと思う一面もあるので、やはり全てのことに対して万能として見るのではなく、ひとつのソフトウェアとして見るのが丁度いいのだろう。そうすればフラットに見ることが出来ると思う。従って、目的や用途に合わせて他社製品も含めてソフトウェアを選んでいくとより活動しやすくなるのだと思う。

[^2]: また、不用意なデータ変換は避けたいというのが本音であり、修正すればいいではないかという意見もあるかとは思うが、気付かないところでデータが変わっていてバグを起こした（自分の作業でバグを起こした）なんてことはしたくないのだ。自分を守るためである。まあ、最終的には事象的に見たときに直すしかないんだが・・・。それでも余計な手間は掛けたくないのが自分の実情だ。

[^3]: ExcelではそのままCSVを開けばこの問題は回避されるが、「データの値が変換される」件が解決できない。しかし、ファイルを読み込んで型を指定する経路を取ると、「データの中に改行が含むと改行される」件が起こるので、両方の問題が解決できない矛盾が発生してしまう。

[^4]: 今週していた仕事でマジで助かったツールである。作者の方にはお礼を申し上げたい。もちろん、完全ではない部分もあると思うが、大量のレコードは読み込めないかもしれない気がしているのと、ある程度のレコードでも操作が重くなるというか機能が反応しづらいように感じるが、それでも今回の問題を解消できることに比べたら天秤に掛けたときに、問題点の解消を取り多少の不便さは受け入れる。最終的には良かったと思うので、要求内容によってはマジで最適なツールになるかと思います。
#20 TabBarControllerにTabを追加する1例

#はじめに
個人のメモ程度の出来なのであまり参考にしないで下さい．


#環境
Xcode：11.2.1
Swift：5.1.2
2019/11


##part1
プロジェクトに`UIViewController`を追加する．

<img width="681" alt="スクリーンショット 2020-02-01 午後11.17.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534708/4c4c8c7a-7d71-ea41-2d06-8661cc34ff5c.png">

<img width="531" alt="スクリーンショット 2020-02-01 午後11.17.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534708/ff3a0560-b0d2-0af5-7ea5-7405698dca51.png">



##part2
`control`キーを押しながら`TabBarController`から`UIViewController`へドラッグ・ドロップする．



##part3
`Relationship Segue`の`View Controllers`を選択する．

<img width="532" alt="スクリーンショット 2020-02-01 午後11.18.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534708/4a4059fc-c50f-3d26-383f-3ec6c084187b.png">




##part4
下のように`Segue`で繋がれていればOK．

<img width="308" alt="スクリーンショット 2020-02-01 午後11.18.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534708/ed1d8217-6012-2ecb-d3ae-6ce437cc1531.png">
Matlabを使った振動制御のシミュレーション


産業機械を動かす際に生じる機械振動を抑えるための制御手法をMATLABを使ってシミュレーションします。下図のような位置制御されたモータとモータに取り付けられた共振系からなるシステムを考えます。今回は，共振が主共振と奇数倍の高調波からなる連生振動系を扱います。
![re0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43995/1421c917-b025-6fe2-2c4e-99173716f15a.png)
ここで，$q$は一般化位置を示し,$q_{\rm tip}$は先端位置，$q_{\rm m}$はモータ位置，$q_{\rm tip}^{\rm cmd}$は先端位置指令とします。$C_{\rm p}$は位置制御器を表し，共振系の主共振を$\omega_1$ [rad/s]であるとします。この制御系に，下図のような$T_{\rm w}$秒の時間遅れとゲイン$m$を用いた先端位置フィードバックと入力整形ゲイン$1-m$を導入します。
![re1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43995/da11d195-fb67-a068-6901-c31da49fa7f7.png)
ここで，時間遅れ量は$T_{\rm w}=\pi/2\omega_1$と決定されるものとします。この単純な制御系によって振動が抑制されます。

```matlab:vib.m
clear;         

s=tf('s');
t_range=0.5;

%Plant parameter
f_std=12.3456789;
w_std=2.0*pi*f_std;

%Compensator
Td=1.0/(4*f_std);
d=-exp(-s*Td);
m=0.6;

%Motor
Kp=22500.0;
Kd=4.0*sqrt(Kp);
Cp=Kp+Kd*s;
Gm=Cp/(s^2+Cp);

%Plant
plant=1;
NumOfHarmonics=25;

for n=1:1:NumOfHarmonics
    w=w_std*(2*n-1);
    plant=plant*w^2/(s^2+w^2);
end

%System
sys=Gm*plant;

%Closed loop
sys_closed=(1-m)*(sys/(1+sys*m*d));

step(sys,sys_closed,t_range);

```
NumOfHarmonicsで共振の個数を設定しています。Matlabの数値計算誤差の影響で制御出力が発散しない限り，どんな値でも振動が止まります。応答結果の一例を以下に示します。
![untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43995/c59bf45e-adcb-2281-239f-24bd2235119e.png)
設計パラメータ$m$を大きくすると応答が遅くなり，オーバーシュートが消えます。微分演算など面倒なことが必要ないので，簡単に使えます。

設計が面倒な時のための自動調整
https://qiita.com/wcrvt/items/59bedde75ac0d6bf7ea1
slackbotを特定のチャンネルでのみ反応するようにする （Python slackbot）

# はじめに

Slackで[slackbot](https://github.com/lins05/slackbot)を利用した自作botを運用しています。
用途別にチャンネルを作成しており、botの各プラグインはそれぞれ専用のチャンネルで実行する、という運用にしております。

しかし、チャンネルの用途とは異なるプラグインを実行してしまうというヒューマンエラーが度々起きており、なんとかしたいと考えていました。

そこで、特定のチャンネルでのみ処理を実行する機構をbotに実装しました。

※本記事にはslackbotの使用方法は記載しておりません

## 検証環境

Python 3.6.1
slackbot 0.5.3

# デコレータによる処理を実行するチャンネルの指定

実行を許可するチャンネルを引数にとるデコレータを作ります。

```Python
import functools


def in_channel(allow_channel):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(message, *args, **kargs):
            channel_id = message.body['channel']
            channel_info = message.channel._client.channels[channel_id]
            channel = channel_info['name']
            if allow_channel not in (channel, channel_id):
                message.reply("Please post in #{}".format(allow_channel))
                return
            return func(message, *args, **kargs)
        return wrapper
    return decorator
```

上記コードでは、引数はチャンネル名/チャンネルIDのどちらでもOKです。

そして、特定のチャンネルでのみ実行したい関数にデコレータを適用します。
私は先ほどのコードを`utils.py`というファイルに記述しています。

```Python
from slackbot.bot import listen_to

from .utils import in_channel


@listen_to("^強い$")
@in_channel("playground")
def tsuyoi(message):
    message.reply("強くない:white_frowning_face:")
```

上記コードでは、 **playground** というチャンネルでのみ、関数`tsuyoi`が実行するように設定しています。

- playgroundチャンネルで発言した場合
![playground.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230909/42d93c53-6598-d3db-ee3f-aa16f281fc08.png)

- playgroundチャンネルで以外のチャンネルで発言した場合
![other.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230909/694a1369-d738-4e15-b1f3-851e88058379.png)

# 注意する点
`@in_channel`はslackbotのデコレータ（上記例では`@listen_to`）よりも**下**に記述してください。
順番が逆だと`@listen_to`の方が先に適用されます。その場合、メッセージが投稿されてしまうことを確認しています。

# おわりに

デコレータでチャンネルを指定することで、用途が異なるチャンネルでプラグインを実行してしまうミスを防ぐことができました。

課題としては、（私の運用では問題ないのですが）チャンネルを1つしか指定できない点です。
複数のチャンネルを指定したい場合は、上記コードを少しいじる必要があります。

## 参考にしたページ
[Limit slackbot responce to certain channel · Issue #152 · lins05/slackbot · GitHub](https://github.com/lins05/slackbot/issues/152)
[Python デコレータ再入門　 ~デコレータは種類別に覚えよう~ - Qiita](https://qiita.com/macinjoke/items/1be6cf0f1f238b5ba01b)
『プロを目指す人のためのRuby入門』で学べること

#『プロを目指す人のためのRuby入門』で学べること

Rubyの書き方はもちろん学べるんだけど、
本書で学習している人に伝えたいことがもっとあるんじゃないかなと、思った。

それは**プログラマーとしての仕事のやり方**みたいなことかなと。

なぜそう思ったかというと理由は２つあって、
ひとつめが、
####コードのわかりやすさを大切にしている
「こういう書き方も出来る」っていう記述があり、
現場ではこれが一般的と説明があるけど、

**場合によって読みやすいほうを書こう**、みたいなことが最終的に書いてあることが多い。

これは恐らく共同開発したときに、（したことないけど）
**共同開発の仲間がコードを読んだとき、
時間が経って自分で読み返したときに**、

そういったときにわかりやすいよう、より効率的に仕事を進めるために必要なことなのかなと、思った。

そして理由のふたつめが、
####細かくテストしながら話を進めている
少しづつテストしながら進めていったほうが、
エラーが出たときに解決できるスピードが違う。

長文を書いて、エラー出ると序盤のほうから修正しないといけないときがある。

あと、インデントを直して読みやすくしたりとか。

書いて→テスト→エラー→デバッグ→書いて・・・

って**ひとつひとつ進めていったほうが効率いい**気がする。

ということで、
**コードのわかりやすさを大切にしている**
**細かくテストしながら話を進めている**
という2つの理由から

**プログラマーとしての仕事のやり方**

を学べていると思った。
普段からコード書くときに、この2つはけっこう意識している。

Paizaのスキルチェックも変数がわかりやすいように、なるべくコードを短く、コメントもしっかり書く。

この辺を意識しながらコードを提出している。
JavaScript: try/catchでエラーが起きても処理を中止させない方法

tryを使うと、まずは処理を恐る恐る実行し、catchでそのエラーを受けた処理をしつつも、そのまま先に処理を進めてくれる。

```js

'use strict';


const name = 1;

try {
    console.log(name.toUpperCase()); // エラーが起きる
} catch (e) {
    console.log(e); // eで取得したエラー内容を表示する
}

console.log('Bye.'); // そして、ここまで来る。

```
G検定を受けた感想

関東在住の新卒1年目のエンジニアです。

1回qiitaで記事書いてみようかとふと思ったのでお試しで投稿します。
次回投稿するかは知りません。

ネタになることなんかあるっけと考えたら2019年11月にG検定受けたしそれについて書きます(何番煎じやねんというツッコミはなしで)
#G検定とは？
日本ディープラーニング協会が実施している資格試験の1つです。
G検定とE資格があります。
E資格は難しい上に時間とお金もかかりますが、G検定は合格率7割(2019年11月の試験)と高く、難易度もそこまでなので合格へのハードルは低めです。AIの仕事に多少なりとも興味ある方は気軽にチャレンジできると思います。

ちなみに受験した動機は、会社が強く取得推奨している資格の1つであること＋大学時代機械学習使ってたので多少前提知識があったから、です。

#対策
勉強期間は1ヶ月くらいでしたが後半はのほほんとしていたので前提知識がある方は2,3週間もあれば十分だと思います。
###買った参考書
![518zmsdTIVL._SX350_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508444/4b451c93-57c2-b805-9fea-40204a50037c.jpeg)
[深層学習教科書-ディープラーニング-G検定-ジェネラリスト-公式テキスト](https://www.amazon.co.jp/深層学習教科書-ディープラーニング-G検定-ジェネラリスト-公式テキスト/dp/4798157554/ref=sr_1_1?hvadid=386583246371&hvdev=c&jp-ad-ap=0&keywords=g%E6%A4%9C%E5%AE%9A+%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88&qid=1580563138&sr=8-1)

日本ディープラーニング協会から出ている公式テキストですが、amazonのレビューでボロクソ叩かれている可哀想な子。
たしかに試験範囲全部網羅しているかと言われたら微妙ですがある程度試験範囲の内容を確認する上では問題ないんじゃないかと思います。
技術的な内容については「え？説明そんだけ？」ってなる部分が多いですがG検定受かる程度なら単語レベル知っとけばだいたいなんとかなります。

![51Ct+64OAXL._SX350_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508444/612c261a-fda9-1ee7-61ff-c85850981223.jpeg)
[徹底攻略-ディープラーニングG検定-ジェネラリスト問題集-スキルアップAI株式会社-明松](https://www.amazon.co.jp/徹底攻略-ディープラーニングG検定-ジェネラリスト問題集-スキルアップAI株式会社-明松/dp/4295005665/ref=sr_1_2?hvadid=386583246371&hvdev=c&jp-ad-ap=0&keywords=g%E6%A4%9C%E5%AE%9A+%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88&qid=1580563138&sr=8-2)
7章に分かれた問題と本番に近い形式の総仕上げが入っている本

###Study-AIの模擬テスト
http://study-ai.com/generalist/
これは絶対やりましょう。なぜなら当日わりとここで出ている問題がそのまま出てくるから。
ぶっちゃけこれやっとけば上の黒の問題集いらなかった、金の無駄(直球)

#試験の感想
2019年11月のテストは総受験者数6580名に対して合格者4652名で合格率は約7割でした。

問題の半分くらいは

・時系列データの解析によく使われる手法は？→RNN
・CNNは〇〇〇〇によく用いられる→画像認識

みたいな単語レベルの内容を知っておけばサクサク解けます。

しかしながら鬼門とも呼べる分野がありまして...
###法律系問題
2,3割くらいがこの系統の問題だったと思います。
こいつらは最後まで残しておき、残り時間ググりまくって対応しました。
G検定は巷では、G(oogle検索力)検定と言われているみたいなのでここでその力を見せつけましょう(適当)

しかし調べてもわからん問題もけっこうありました。
2019年に施行された〇〇法の～とか言われても知らんがなって感じでした。

こういう問題はAI白書とか読んどけば多少は対応出来たんですかね？
まぁ法律系の問題なんか対策する気起きないでしょうけど...

ともあれ法律系の問題がズタボロだった僕でもその他の問題を無難にこなせば普通に合格出来たのでここはググって対応ぐらいの気持ちでいいかもしれません。

#最後に
初投稿してみましたがいかがだったでしょうか・
次回投稿するかどうかは知りません。

そろそろ次の資格取得目指そうかと思いつつも手が動かない昨今...次はLPIC、CCNA、応用情報あたりかな？
pythonで関数合成とカリー化してみた

# pythonにはpartialがある
だけど、カリー化がない。俺悲しい。
だから、自分で位置引数数えるカリー関数書いた。

# 関数合成
まず、関数合成を書いてみた。シンプルでしょぼい。

```python
def compose(*funcs: Callable) -> Callable:
    '''
    >>> compose(multest, multest)(4)
    16
    '''
    def composed(*args: Any) -> Any:
        return reduce(lambda x, y: y(x), (funcs[0](*args),) + funcs[1:])
    return composed
```

## 関数のカリー化

仕組みは、位置引数の数を調べておいて、そのぶんだけpartialするというシンプルなもの。
なので、うまく動かんこともある。

```python
def _curry_one(func: Callable) -> Callable:
    def wrap(*args: Any, **kwargs: Any) -> Any:
        return partial(func, *args, **kwargs)
    return wrap


def curry(num_of_args: Optional[int] = None) -> Callable:
    '''
    >>> fnc = curry(2)(multest2)
    >>> fnc(2)(3)
    6
    >>> fnc = curry()(multest3)
    >>> fnc(2)(3)(4)
    24
    '''
    def curry_wrap(func: Callable) -> Callable:
        length_of = compose(filter, list, len)
        if num_of_args:
            num = num_of_args
        else:
            def is_empty(x): return x.default is inspect._empty
            num = length_of(is_empty,
                            inspect.signature(func).parameters.values())
        for n in range(num - 1):
            func = _curry_one(func)
        return func
    return curry_wrap
```
これ、カリー化する時に引数の数を数えて、positional引数の数だけカリー化する。
カリー化する回数は指定することも出来る。
でも、実用上2で固定でいい感じもしなくはない。

## 何故カリー化なんですか？partialでは駄目なんですか？
別にpartialでもいいけど、このカリー化ならデコレータとして使える。

```python
@curry()
def test(x, y, z):
    return x * y + z
```


あと、高階関数として使う時に時々便利。主に場合分けが必要なときとか、
starmap持ち出さなきゃいけない時とか。
例えば下記の最後が僕には読めない。(書けはする)

```python
def plus(x, y):
    return x * y

result = list(map(partial(plus, 3), range(4)))
```

こいつpartial切り離してもこう。

```python
def plus(x, y):
    return x * y

plus3 = partial(plus)
result = list(map(plus3, range(4)))
```

名前空間が若干アレ…plushogeが増えるの気持ち悪い。
こいつをこう書ける


```python
@curry()
def plus(x, y):
    return x * y

result = compose(map, list)(plus(3), range(4))
```

# こんな事して大丈夫？
駄目に決まってるじゃん、pythonは誰が書いても同じになるのが良い所。
故に上記は使ってはいけない。

解散

# 駄目なら何故こんなことした？
個人プロジェクトでnumpyを使っててな。
自業自得なんだが、このような雰囲気のコード書いてしまって自分で読めなくて絶望したん。

```python
np.save(fname, baseline(np.square(fft(data.mean(axis=1)))))
```

これ、状況的に情状酌量の余地(あるのか？)を述べますと、科学計算パッケージなので、
とってもいっぱいの数学の変数があって、名前空間がヤバかったんです…。
もし、ここにカリー化と関数合成があれば、これがこうなるんだよ？

```
mean = curry(np.mean)
save = curry(np.save)
compose(mean(axis=1), fft, np.square, np.std, save(fname))(data)
```

...だいぶじゃない？
個人プロジェクト無罪説。