OmniAICreator/Qiita-1.07M huggingface dataset:
SpringBoot+MVCで、リクエストパラメータの型変換を登録する

# SpringMVCによるリクエストパラメータ自動型変換
SpringMVCではリクエストパラメータを適切な型に変換します。デフォルトの型変換が提供されているので、これ以外の型（自作したクラスに格納する、自動的に解決する型とは別の型）に格納したい場合は、SpringMVCの設定にて型変換に登録します。

例：日付の入力をjava.time.LocalDateに変換する（デフォルトでjava.util.Date）場合

```java:SampleModelController.java
import java.time.LocalDate;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import lombok.Data;

@Controller
@RequestMapping("/sample")
public class SampleModelController {
	@GetMapping
	public ModelAndView sample(ModelAndView mnv, @ModelAttribute SampleModel model) {
		mnv.addObject("model", model);
		return mnv;
	}

	@Data
	public static class SampleModel {
		private String name;
		private LocalDate birthday;
	}
}
```

SampleModelのbirthdayが、LocalDate型です。今回はすべてのパラメータに対し、全般的にSpringMVCの設定にて変換対象にします。

```java:WebConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
	@Override
	public void addFormatters(FormatterRegistry registry) {
		registry.addConverter(new StringToLocalDate());
	}
}
```

StringToLocalDateは、`org.springframework.core.convert.converter.Converter` を継承したクラスです。

```java:StringToLocalDate.java
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import org.springframework.core.convert.converter.Converter;

public class StringToLocalDate implements Converter<String, LocalDate> {

	@Override
	public LocalDate convert(String source) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d");
		return LocalDate.parse(source, formatter);
	}

}
```
ひらがな、カタカナ、英数字、URLを判定するExtension

## コード


```Swift
import Foundation
extension String {
    /// ひらがなかどうか
    var isHiragana: Bool {
        let range = "^[ぁ-ゞ 　]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// カタカナかどうか
    var isKatakana: Bool {
        let range = "^[ァ-ヾ]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }
    
    //// 英数字かどうか
    var isAlphanumeric:Bool {
        let range = "[a-zA-Z0-9]+"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    //// URLかどうか
    var isUrl: Bool {
        let linkValidation = NSTextCheckingResult.CheckingType.link.rawValue
        guard let detector = try? NSDataDetector(types: linkValidation) else { return false }
        
        let results = detector.matches(in: self, options: .reportCompletion, range: NSMakeRange(0, self.characters.count))
        return results.first?.url != nil
    }
}
```

ひらがな、カタカナ、英数字は`NSPredicate`を用いて正規表現でチェックしています。
正規表現のところさえ変えれば他のものも判定出来ます。

URLは`NSDataDetector`を用いてチェックしています。
`NSTextCheckingResult.CheckingType`で判定する形式を設定しております。
電話番号のチェックやスペルチェック等もできるようです。

---
簡易的なバリデーションチェックを行いたい時に使用しています。
役に立てば幸いです。
ありがとうございました。
pymodbusを使ってMac上でmodbus の疎通確認

# setup
pymodbusのインストール。手元の環境では、sixのエラーが出たので以下でインストールした。

```sh
sudo pip install pymodbus --ignore-installed six
```

# modbus の資料
### pymodbus
Github。仕様書、サンプルコードがいろいろある。
https://github.com/riptideio/pymodbus

### modbus
まだ一部しか見てませんが、こちらが参考になりそう。
https://www.m-system.co.jp/mssjapanese/kaisetsu/nmmodbus.pdf

# Server (Slave)
``` python:server.py
from pymodbus.server.sync import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer
import logging

logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

store = ModbusSlaveContext(
    di=ModbusSequentialDataBlock(0, [17] * 100),
    co=ModbusSequentialDataBlock(0, [17] * 100),
    hr=ModbusSequentialDataBlock(0, [17] * 100),
    ir=ModbusSequentialDataBlock(0, [17] * 100))
context = ModbusServerContext(slaves=store, single=True)
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.0'
StartTcpServer(context, identity=identity, address=("localhost", 5020))


```

# Client (Master)
``` python:client.py
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
import logging

FORMAT = ('%(asctime)-15s %(threadName)-15s '
          '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

UNIT = 0x1


def run_sync_client():
    client = ModbusClient('localhost', port=5020)
    client.connect()
    log.debug("Reading Coils")
    rr = client.read_coils(1, 1, unit=UNIT)
    log.debug(rr)
    client.close()


if __name__ == "__main__":
    run_sync_client()

```

`server.py` を実行した状態で、`client.py` を実行することで、無事疎通確認ができました。
UIImageをnKB以下のJPEGに変換するExtension

「UIImageを絶対にnKB以下のJPEGで送らないといけない！」ということがあり、作りました。

## コード

```Swift
import UIKit

extension UIImage {
    func compressedJpegData(toKB:Int) -> Data? {
        guard let resized = self.resized(withPercentage: 0.75) else { return nil }
        guard var data = resized.jpegData(compressionQuality: 0.9) else { return nil }
        
        let byte = [UInt8](data)
        if (byte.count / 1024) >= toKB {
            // toKBを超えてた時
            guard let againImage = UIImage(data: data) else { return nil }
            guard let rescalingData = againImage.compressedJpegData(toKB: toKB) else { return nil }
            data = rescalingData
        }
        return data
    }
    
    func resized(withPercentage percentage: CGFloat) -> UIImage? {
        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
        return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }
}
```

## やっていること

```Swift
func compressedJpeｔgData(toKB:Int) -> Data?
```
これは、指定したサイズ(容量的な)まで縮めるメソッドです。
toKBに指定したサイズに収まるまで再帰的に呼ばれます。

```Swift
guard let resized = self.resized(withPercentage: 0.75) else { return nil }
guard var data = resized.jpegData(compressionQuality: 0.9) else { return nil }
```
まずサイズ(見た目的な)を縮小し、JPEGにエンコードします。
self.resized(withPercentage: 0.75)は以下のような処理になっています。

```Swift
func resized(withPercentage percentage: CGFloat) -> UIImage? {
    let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
    return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
        _ in draw(in: CGRect(origin: .zero, size: canvas))
    }
}
```
↑で、縮小率を指定してUIImageを縮小することが出来ます。アスペクト比は保持されます。

```Swift
let byte = [UInt8](data)
if (byte.count / 1024) >= toKB {
    // toKBを超えてた時
    guard let againImage = UIImage(data: data) else { return nil }
    guard let rescalingData = againImage.compressedJpegData(toKB: toKB) else { return nil }
    data = rescalingData
}
return data
```
JPEG化したDataをバイト配列に入れ、サイズを見ます。
`byte.count`はJPEGのバイト数を表しています。今回はKBで計算したいので1024で割ります。
割った結果が`toKB`を下回っていればそのまま`data`を返し、超えていた場合は再度UIImageにして圧縮処理します。
以上の流れを、サイズが`toKB`を下回るまで行います。

---
もしよかったら使っていただけるとありがたいです。いいねも押していただけると喜びます。
不明点、不足点、改善点など、何でもコメントしてください。
ありがとうございました。
最速で動画をGifに変換する

(MacOSです。Homebrewは入っている前提で進めます。)

変換するの面倒...
ターミナルから変換できるようにしたけどいちいちコマンド覚えてない...
と思って、簡単に実行できるようにしたので紹介します。

## なにをするか
ターミナルで一発で変換できるように、シェルスクリプトを作っておきます。
完了するとこんな感じに変換できるようになります。
![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208118/42098911-f42e-a0c6-a2ef-174927e3afd5.gif)

順を追って、方法を紹介します。

## 1. ffmpegを導入
Gifへの変換には[ffmpeg](https://www.ffmpeg.org/)を使用します。
インストールは以下のコマンド。

```bash
brew install ffmpeg
```

動画の変換は以下のコマンドで行えます。

``` bash
ffmpeg -i 変換元のファイル名 保存先のファイル名
```

拡張子を見ていい感じに変換してくれるので、ファイル名には拡張子も含めてください。
また`-r`でフレームレートも指定することができます。

## 2. シェルスクリプトを書いたファイルを作成

ファイルを作成し、コマンドをそこに保存しましょう。
今回は「toGif」という名前でファイルを作成し、以下のコマンドを保存しました。
(このファイル名が、最終的に呼び出す時のコマンドになります)

```bash:toGif
#!/bin/bash
fileName=`basename $1`
name=${fileName%.*}

ffmpeg -i $1 -r 10 ~/Desktop/$name.gif
echo "Saved to desktop."
```

`$ toGif 動画のパス`の形式で実行する事を想定しています。
`$name.gif`の拡張子を変えれば他の形式に変換することもできます。
(MP4とか…それ以外浮かばないけど…)

#### 少しだけ解説
``fileName=`basename $1` ``では、
第一引数(`$1`)として受け取ったファイルパスからファイル名を取り出し、
``name=${fileName%.*}``で、ファイル名から拡張子を取り除いています。

``ffmpeg -i $1 -r 10 ~/Desktop/$name.gif``
は、10FPSのGifに変換して、同じ名前でデスクトップに保存するように指定しています。

## 3. パスを通す
作成したファイルにパスを通します。(→ コンソールから呼び出せるようにします)
パスを通すにはホームディレクトリにある`.bash_profile`に、以下を追記します。
`.bash_profile`は、ログイン時に一度実行されるファイル的なものです。(認識間違っていたら教えて下さい)

```bash
export PATH=$PATH:作ったファイルのパス
```

私はDocuments下にscriptというフォルダを作り、そこにパスを通しているので

```bash
export PATH=$PATH:~/Documents/script
```
こんな感じのものを追記してあります。

(その他作成したシェルスクリプトもそこにまとめてあります。いちいちパス通し直さなくていいのでおすすめです。)</span>

`.bash_profile`を更新した後は、

```bash
source ~/.bash_profile
```
で再読み込みしましょう。

以上で、コンソールから最速(?)で動画をGifへ変換できるようになりました。おめでとうございます。

---
もしよければ「いいね」していただけると喜びます。
類似記事の「[最速で画像をリサイズする](https://qiita.com/akaneburyo/items/7a07a203d88e98218ed9)」もどうぞ。

「もっとこうしたほうがいいよ！！」「これもおすすめだよ！！」などあればぜひお教えください。
ありがとうございました。
最速で画像をリサイズする

(MacOSです。)

変換するの面倒...
ターミナルからリサイズできるけどいちいちコマンド覚えてない...
と思って、簡単に実行できるようにしたので紹介します。

## 何をするか
ターミナルで一発でリサイズできるように、シェルスクリプトを作っておきます。
完了するとこんな感じに変換できるようになります。
![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208118/796cc56e-3d37-ad47-e208-fa3e5ee283fb.gif)

順を追って、方法を紹介します。

## 1. シェルスクリプトを書いたファイルを作成

画像のリサイズには「sips」コマンドを使用します。
リサイズする場合は

```bash
sips -Z 縮小後の横幅 画像ファイル -o 出力先
```
こんなかんじ。

ファイルを作成し、コマンドをそこに保存しましょう。
今回は「resize」という名前でファイルを作成し、以下のコマンドを保存しました。
(このファイル名が、最終的に呼び出す時のコマンドになります)

```bash:resize
#!/bin/bash
fileName=`basename $1`
name=${fileName%.*}
extension=${fileName##*.}

sips -Z $2 $1 -o ~/Desktop/$name-r.$extension
echo "Saved to desktop."
```

`$ toGif 動画のパス`の形式で実行する事を想定しています。
`$name.gif`の拡張子を変えれば他の形式に変換することもできます。
(MP4とか…それ以外浮かばないけど…)

#### 少しだけ解説
``fileName=`basename $1` ``では、
第一引数(`$1`)として受け取ったファイルパスからファイル名を取り出し、
``name=${fileName%.*}``でファイル名のみ、
``extension=${fileName##*.}``で拡張子のみ取り出しています。

``sips -Z $2 $1 -o ~/Desktop/$name-r.$extension``
ここでは、サイズとファイルを指定してリサイズしています。
保存先はデスクトップ、ファイル名は元のものに「-r」をつけたものを指定しています。

## 2. パスを通す
作成したファイルにパスを通します。(→ コンソールから呼び出せるようにします)
パスを通すにはホームディレクトリにある`.bash_profile`に、以下を追記します。
`.bash_profile`は、ログイン時に一度実行されるファイル的なものです。(認識間違っていたら教えて下さい)

```bash
export PATH=$PATH:作ったファイルのパス
```

私はDocuments下にscriptというフォルダを作り、そこにパスを通しているので

```bash
export PATH=$PATH:~/Documents/script
```
こんな感じのものを追記してあります。

(その他作成したシェルスクリプトもそこにまとめてあります。いちいちパス通し直さなくていいのでおすすめです。)</span>

`.bash_profile`を更新した後は、

```bash
source ~/.bash_profile
```
で再読み込みしましょう。

以上で、コンソールから最速(?)で画像をリサイズできるようになりました。おめでとうございます。

---
もしよければ「いいね」していただけると喜びます。
類似記事の「[最速で動画をGifに変換する](https://qiita.com/akaneburyo/items/0bbb3ba28705040b6aa1)」もどうぞ。

「もっとこうしたほうがいいよ！！」「これもおすすめだよ！！」などあればぜひお教えください。
ありがとうございました。
centos8でlocaleに ja_JP.UTF-8 がないときの対応

以下のコマンドで言語パックを追加します。
(2019/11/08修正：locale以外にも日本語パッケージが含まれていない可能性があるので、パッケージをlangpack-jaに変更）

```bash
# dnf -y install langpack-ja
```

わかれば簡単なことだけど、ハマってしまった。

参考：
https://bugzilla.redhat.com/show_bug.cgi?id=1677927
https://www.server-world.info/query?os=CentOS_8&p=japanese
wordpress サイトのタイトル、キャッチフレーズ取得

サイトの情報を出力
bloginfo()

```
タイトルを出力
<h1><?php bloginfo( 'name' ); ?></h1>
キャッチフレーズを出力
<p><?php bloginfo( 'description' ); ?></p>
```

※サイト名は直接コードに書かない！
　wordpressで設定しておけば、bloginfoを使用して取得が可能
　コードを変更する必要がなくなるので便利

他のパラメータは以下URL参照
[bloginfoパラメータ](https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/bloginfo)
オレオレ証明書を適当に作ってchromeでアクセス出来なくなった時

同じ轍を踏んだ時のための覚書として。。。

# 状況
ローカル環境で開発をする時に、諸事情によりSSL認証をオレオレ証明書を作って認証を通すことはあると思います。
もちろん証明書の情報が正しくなければ怒られてしまい、作り直しても怒られっぱなしになったりします。

# 解決方法
こちらに載っておりました
https://masshiro.blog/chrome-hsts-error/

[chrome://net-internals/#hsts](chrome://net-internals/#hsts) にアクセスすると、今のchromeのレイアウトではこんな感じでした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160396/f184299f-c509-8ede-4b00-05bd2cd3c643.png)

一番したの「Delete domain security policies」に該当のドメインを入れて認証情報を削除して証明書を作り直して再アクセス！
これで解決しました。

# まとめ
証明書は正しく作るべきだよねわかる
いちいちgit pull origin ブランチ名しない

```terminal
git branch --set-upstream-to=origin/リモートのブランチ名 ローカルのブランチ名
```

これやるとトラッキングしてくれるようになるので、わざわざ `git pull origin master` とかやらずに `git pull` で現在のブランチ名を設定したリモートブランチにリンクさせてpullを実行してくれる。
homebrewをデフォルト以外にインストール  permission deniedなど

## Homebrewをどこにインストールするか。もしくは、permission deniedでインストールできない時。

基本的な情報は、homebrewのHPにあります。

https://brew.sh/

## [基本] Install Homebrew
```/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"```

## 他にインストール

ここにあります。https://docs.brew.sh/Installation#alternative-installs

```mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew```

環境変数の設定 $ cd /Users/username で自分のhomeにいるとして。

~/.bashrc あたりに、
```export PATH=$HOME/homebrew/bin:$PATH
export HOMEBREW_CACHE=$HOME/homebrew/cache```

### ちなみに、homebrewでは、非推奨な方法だそうです。

## 雑談
いろいろな作業環境が考えられるものの、ユーザが共通のバージョンなりコンパイルオプションを使うとは限らないので、それぞれのユーザが個別のコンパイルする方が良いように思います。少なくとも、私は、自分の使いやすいオプションでコンパイルしたいです。macでは、基本的に一人1台環境なので、どちらでも良いかと。

# 新発見
homebrewはLinuxでも使えるようです。よく見ていないのでわかりませんが。必要かどうかと言われれば、必要ないのですが、気になりました。


## 参考にさせていただきました。
https://teratail.com/questions/107847
https://qiita.com/yotsak83/items/c37e91542d2c4518c65b
stylelint "at-rule-no-unknown" ルールでエラー

Sassファイルの整形（Lint）をしてくれるツールはいろいろありますが、中でも[stylelint](https://stylelint.io/)がいい感じなので好んで使っています。

### "at-rule-no-unknown" でエラー発生
ところが、["at-rule-no-unknown"](https://stylelint.io/user-guide/rules/at-rule-no-unknown#at-rule-no-unknown)すなわち「標準的でない[@-規則](https://developer.mozilla.org/ja/docs/Web/CSS/At-rule)」というルールにおいて、これを適用させたくなかったので`false`を設定したところ、`Invalid Option: Unexpected option value "false" for rule "at-rule-no-unknown"`と怒られてしまいました。

```json:stylelintrc.json
"rules": {
  "at-rule-no-unknown": false,
}
```
上記の書き方だとエラーになります。`false`を`null`にしてもダメです。
次のようにoptionを`true`にした上で、例外ルールを記述するように書き直すとエラーが出なくなりました。

```json:stylelintrc.json
"rules": {
  "at-rule-no-unknown": [true,
    {"ignoreAtRules": ["include","mixin","each"]}],
}
```
これはstylelintの"at-rule-no-unknown"ルールのoptionに`true`しかないのが原因でした。`true`があるなら`false`もあるじゃん！という思い込みが罠でした。これはなかなかの初見殺し…
JavaFXプロジェクトを実行可能なJARファイルとしてエクスポートする

こんにちは、Androidエンジニアの忽那です。

現在、社内用に受付システムを空いた時間で開発中です。
受付からの通知を社内で受け取る為に、PC用GUIアプリを作成しようと思い、IntelliJ IDEAでJavaFXプロジェクトを作成しました。

Javaそのままでも良かったのですが、せっかくなのでKotlinを使いたかったので、JavaFXをKotlinで書きやすくしてくれる[TornadoFX](https://tornadofx.io/)というライブラリを使ってみました。
この辺のシステムの実装方法はいずれ別記事として出したいと思います。

<b>本題はタイトルにあるように、TornadoFXを使って作成したJavaFXプロジェクトを実行可能のJARファイルとしてエクスポートする方法です。</b>


アプリの開発が完了し、いざエクスポートしようとしたところ
<b>方法が全くわからん！</b>

ググったら情報がたくさん出てきますが、どうやっても上手くいかない...
ビルドが通らなかったり、jar作っても起動時にMainクラスが見つからないと怒られたり、ライブラリが存在しないと怒られたり...

ということで、詰まったところと解決方法を備忘録として残しておきます。
ちなみに今回のプロジェクトはGradleプロジェクトです。Mavenプロジェクトの場合は参考にならないと思うのでご了承ください。


## 詰まったところ
#### ①そもそもビルドが通らない
これはJDKのバージョンが原因のことが多いです。
JavaFXはJDK11以降はJDKに含まれていないようです。
私の環境ではIntelliJ IDEAで使うJDKのバージョンを10にしたところ上手くいきました。
まずは[Oracleの公式](https://www.oracle.com/java/technologies/java-archive-javase10-downloads.html)からJDK10を入手しましょう
インストール後、IntelliJ IDEAで使うJDKのバージョンを選択しましょう
プロジェクトを開き、
File→ProjectStructure→Platform Settings→SDKsの画面までいき、＋→JDKを選択し、
インストールしたJDKのあるフォルダを選択します。
Windows環境だと少し違うかもしれませんが、Macの場合は
<b>Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home</b>
を選択すると上手くいきました。参考にしてください。
そのあと、再びProjectStructure画面で
ProjectSettings→Project→ProjectSDKまでいき、先ほど追加したJDK１０を選択しましょう。

これでJavaFXプロジェクトのビルドが通るようになったはずです。

#### ②IntelliJ IDEAのBuildArtifactsでJARを生成しても起動時にエラーが発生する
前提として、IntelliJ IDEAのBuildArtifactsという機能を使えばJARファイルをエクスポートすることができます。
こちらはアーティファクトの設定でJavaFX Applicationを選択することができます。
しかし、バージョンのせいなのかわかりませんが
<b>私はこちらの機能ではどうしても正常に動くJARファイルをエクスポートすることができなかったので、諦めました。</b>
ではどうすればいいのか、というのを次の項目で説明します。

## 解決法
#### プラグインを使ってfatJarファイルを生成する
fatJarというのは依存関係のあるライブラリを全て内包したJARファイルのことです。
実行するPCの環境に左右されることもありませんし、ライブラリのクラスパスをマニフェストで指定する必要もありません。
ただ、ライブラリを全て含んでいる分、ファイルサイズは大きくなります。

使ったプラグイン：[Gradle Shadow](https://imperceptiblethoughts.com/shadow/)
[こちらの記事](https://qiita.com/suin/items/641c1c1ec9ab5447221e)を参考にさせていただきました。
まずはbuild.gradleに以下を追記し、プラグインを使用できるようにします。

```gradle

apply plugin: "com.github.johnrengelman.shadow"
...
buildscript {
    dependencies {
        classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0"
    }
}
```

次に、build.gradleに生成するjarの設定を追記します

```gradle
jar {
    manifest {
        attributes ('Main-Class': 'MainKt', "Implementation-Title": "Gradle",
                "Implementation-Version": 1)
    }
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

```

間違えやすいのが

```gradle
'Main-Class': 'MainKt'
```
の部分です。
今回はメインクラスとして、「Main.kt」というファイルを作っています。
この場合は「MainKt」という書き方で指定しないと認識してくれないので注意してください。
Javaファイルの場合は「Main」で大丈夫です。ややこしいですね...

build.gradleの設定が完了したら、ターミナルを開き、アプリのルートディレクトリまで移動し、以下のコマンドを実行することでjarファイルが生成されます。

```
$ ./gradlew shadowJar
```

[アプリディレクトリ]/build/libs/に、
[アプリ名]-all.jarというファイルが生成されているはずです。
JavaFxアプリをfatJarで生成したので、これをダブルクリックすればそのまま動きます。

以上です。
アプリケーションの開発そのものより実行可能ファイルの生成に苦労するという、想定外の展開になりましたが、なんとかなりました。
同じところで詰まっている方は参考にしていただければ幸いです。
アコーディオンの速度を統一する

```index.html
<!DOCTYPE html>
<html>
    <head>

        <link rel="stylesheet" href="./index.css">
    </head>
    <body>

        <div class="a">
            <button type="button" class="toggle button">aaa</button>
            <div class="area">
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
            </div>
        </div>
        <div class="a">
            <button type="button" class="toggle button">aaa</button>
            <div class="area">
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
            </div>
        </div>
        <div class="a">
            <button type="button" class="toggle button">aaa</button>
            <div class="area">
                aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
            </div>
        </div>

        <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
        <script>
            $(function() {
                var select = document.getElementsByClassName("area");
                var button = document.getElementsByClassName("button");
                var height = [];
                var dur = [];

                for(var i = 0; i < select.length; i++) {
                    console.log(select[i]);
                    height[i] = $(select[i]).height();
                    dur[i] = height[i] / 0.1; /*0.1は任意の速度*/
                    $(select[i]).css({display: "none"})
                    $(button[i]).addClass("button" + i);
                };

                var toggleFunction = function(button, index){
                    $(button).click(function() {
                        $(this).next().slideToggle(dur[index]);
                    });
                };

                toggleFunction(".button0", 0);
                toggleFunction(".button1", 1);
                toggleFunction(".button2", 2);



            });









        </script>
    </body>
</html>

```

```index.css
.a {
    width: 100px;
    display: block;
}
.a > button {
    width: 100%;
}
.a > .area {
    width: 100%;
    word-break: break-all;
}

```
Flask開発　導入編

### 主な特徴
- Python用のマイクロウェブフレームワーク。
- FlaskはWebフレームワークで軽量で機能がそこまで備わっていないことが特徴。
- Djangoほどたくさんの機能が備わってない。余分な機能がない。

#### DjangoはMVC、FlaskはMVT
Django等のMVCモデルについては以下

Model：ビジネスロジックを記述。データベースアクセスを伴うことが多い
View：画面描画を担当。ユーザからの入力も受け付ける
Controller：URLを振り分ける司令塔の役割。ビューからのデータをモデルに渡したり、その逆も行う

一方で、FlaskはMVCではなく、MVTという形式を取っている。
これは、Model、View、Templateの頭文字。 MVCとMVTは、内容はほぼ同じだが、それぞれの役割が異なる。

Model : MVCモデルのModelと同じ役割
View : MVCモデルのControllerと同じ役割
Template : MVCモデルのViewと同じ役割

### 仮想環境構築～Flaskインストール手順

#### 環境
- Python3.6
- Flask1.1.1
- CentOS7

1.作成したプロジェクトのディレクトリへ移動。今回はFlaskAppというプロジェクト名。

```
cd FlaskApp
```

2.venvで仮想環境を作成する（最後のvenvはファイル名なのでなんでもよい）

```
python3 -m venv venv
```

3.仮想環境を実行する

```
source venv\bin\activate
```

4.Flaskをインストールする

```
pip install Flask
```

5.Flaskがちゃんとインストールされたか確認

```
pip freeze 
```

以下のように感じで表示されてたらとりあえずOK

```
Click==7.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
Werkzeug==0.16.0
```

### 簡単なアプリケーション作成してみる
以下のソースを作成する。ファイル名をviews.pyとする。

```python
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World'

if __name__ == '__main__':
    app.debug = True
    # Linux環境下でアプリを起動する場合、以下のように明示的にIPとポート番号を指定しておいた方が良い。port番号の5100は適当。
    app.run(debug=True, host='0.0.0.0', port=5100)
```

【ソースコード11行目補足】
- hostキーワード引数: サーバのIPアドレスを指定する。
- portキーワード引数: ポート番号を指定する。指定しなければ、デフォルトではポート番号は5000。
- debugキーワード引数: デバックモードを有効にするかどうかを指定する。指定しなければ、デフォルトでは無効。

以下のコードでアプリケーションを実行する

```
python views.py
```

ブラウザ上にHello Wordが表示されればOK
※Windows上でVirtualBoxを使用してLinux環境化で開発を行っている場合、IPに注意する必要あり。
Java メソッド一覧 (備忘録)(工事中)

#java メソッド一覧

##◆java.util.*;
**・Collections.unmodifiableXXX(【ListやMapのインスタンス】);** 
※java11からはfinal指定だけでよくなっているっぽい

```java

//finalだけだと再代入はできないが、要素の追加・削除ができてしまう。
//unmodifiableXXXによって要素の変更をできなくする。
//変更しようとすると「UnsupportedOperationException」がthrowされる。

//List (インスタンスイニシャライザの行末にセミコロンはつけない)
private static final List<String> LIST_1 = Collections.unmodifiableList( new ArrayList<String>() {{ add("X"); add("Y"); }} );

//Map
private static final Map<Integer, String> MAP_1 = Collections.unmodifiableMap( new HashMap<Integer, String>() {{ put(1, "X"); put(2, "Y"); }} );
```


##◇Collectionインターフェースの主なメソッド

|メソッド名                        |説明                               |
|:--------------------------------|:----------------------------------|
|boolean add(E e)                 |引数の要素をコレクションに追加する。この呼び出しの結果、コレクションが変更された場合は、trueを返す|
|void add(int index, E element)   |指定した位置に要素を追加する。なお、その位置とそれ以降に要素があればそれらを移動させ、各要素のインデックスに1を加える|
|void clear()                     |このコレクションからすべての要素を削除する  |
|boolean contains(Object obj)|指定された要素objがこのコレクション中に存在する場合はtrueを返す|
|boolean containsAll(Collection<?> c)|指定されたコレクションの要素がすべてこのコレクションに含まれている場合はtrueを返す|
|boolean isEmpty()|このコレクションに要素が1つも含まれていない場合はtrueを返す
|boolean remove(Object o)|引数に指定された要素を削除し、要素が削除された場合はtrueを返す|
|boolean removeAll(Collection<?> c)|メソッドの引数に指定されたコレクションにあるすべての要素をこのコレクションから削除し、このメソッド呼び出しの結果、このコレクションの内容に変化があった場合はtrueを返す|
|Iterator<E> iterator()|このコレクションの要素に対する反復子を返す|
|Object[] toArray()|このコレクションの要素がすべて格納されている配列を返す|
|<T> T[] toArray(T[] array)|このコレクションのすべての要素を含む配列を返す。Tは、配列要素のデータ型を返す|
|int size()|コレクション中の要素数を返す|
|メソッド名                        |説明                               |
|メソッド名                        |説明                               |
ActiveAdminで、indexのカラムにレコードの状態によってクラスをつける

備忘録。

# 状況

Userというモデルがあったとして、

```ruby
index do
	column(:name)
	column(:address)
	column(:status)
en
```

のようなとき、特定のカラムだけ色を変えるなどでクラスをつけたい場合、

```
column(:status, class: 'red')
```

とすると思う。


# だめな例

この方法では、statusによって色を変えたいなどでクラスをつけたい場合に、

```ruby
column(:status, class: status)
```

や

```ruby
column(:status, class: user.status)
```

のように書くことはできない。ここの時点でUserのインスタンスを取得する手段がないため、
NoMethodErrorになってしまう。



では、どうするかというと、

```ruby
column(:status) do |user|
  current_arbre_element.add_class user.status
  user.status
end
```

のようにしてあげるとできる


# なんでそうなるのか

ActiveAdminのindex配下では、selfがActiveAdmin::Views::IndexAsTableというクラスのインスタンスになっている。

このクラスは、#current_arbre_elementというメソッドを持っていて、この戻り値で

Arbre(ActiveAdminの内で使っている、HTMLのヘルパーgem)か、ActiveAdmin::Views::配下の、HTMLオブジェクトを表しているクラスのインスタンスを返すようになっている。

このクラス達は、add_classなど、自分自身を編集するメソッドを持っているので、そこにクラスに設定したい値を渡してあげるという寸法。

# おまけ
パネルとかだったら、以下のissueの下の方の方法でいける。
https://github.com/activeadmin/activeadmin/issues/1615

# あとがき

ドキュメントを漁っても見つからず、自分でメソッドを漁る羽目になった。
チェック対象の配列に'ある要素'が存在するかを判定する方法

チェック対象の配列にチェックしたい要素が存在するかを判定するTipsです。

## いずれか or 組み合わせ を判定する

```js
const checkList = ['apple', 'melon', 'lemon'];

const fruits = ['apple', 'melon', 'lemon'];
fruits.every(fruit => checkList.includes(fruit)); // true

const fruits2 = ['apple', 'melon', 'lemon', 'orange'];
fruits2.every(fruit => checkList.includes(fruit)); // false

const fruits3 = ['apple', 'melon'];
fruits3.every(fruit => checkList.includes(fruit)); // true
```

## 別の書き方

```js
const checkList = ['apple', 'melon', 'lemon'];

const fruits = ['apple', 'melon', 'lemon'];
const size = new Set([...fruits, ...checkList]).size;
checkList.length === size; // true

const fruits2 = ['apple', 'melon', 'lemon', 'orange'];
const size2 = new Set([...fruits2, ...checkList]).size;
checkList.length === size2; // false

const fruits3 = ['apple', 'melon'];
const size3 = new Set([...fruits3, ...checkList]).size;
checkList.length === size3; // true
```



他に良い方法があればご教授ください！
【個人メモ】ローカルにインストールされていないRailsのバージョンのインストール方法

#現象

```
rails _5.2.3_ new kenban
```
でイントールしようとした所、下記のエラーが出た。

```
$ rails _5.2.3_ new kenban
Traceback (most recent call last):
        4: from /home/ec2-user/.rvm/gems/ruby-2.6.3/bin/ruby_executable_hooks:24:in `<main>'
        3: from /home/ec2-user/.rvm/gems/ruby-2.6.3/bin/ruby_executable_hooks:24:in `eval'
        2: from /home/ec2-user/.rvm/gems/ruby-2.6.3/bin/rails:23:in `<main>'        1: from /home/ec2-user/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0/rubygems.rb:303:in `activate_bin_path'/home/ec2-user/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0/rubygems.rb:284:in `find_spec_for_exe': can't find gem railties (= 5.2.3) with executable rails (Gem::GemNotFoundException)
```

Rails5.1, Rails5.2のバージョンを使いたかったので、下記のコマンドを使った。

```
gem install rails -v 5.2.3
```

その後もう一度

```
rails _5.2.3_ new kenban
```
を使うと途中までインストールできたものの

``` 
HEADS UP! i18n 1.1 changed fallbacks to exclude default locale.
But that may break your application.

Please check your Rails app for 'config.i18n.fallbacks = true'.
If you're using I18n (>= 1.1.0) and Rails (< 5.2.2), this should be
'config.i18n.fallbacks = [I18n.default_locale]'.
If not, fallbacks will be broken in your app by I18n 1.1.x.

Post-install message from chromedriver-helper:
```
このようなエラー文が出てきた。

#解決策

そのため以下URL参照。
https://makeslife-better.com/rails-_5-2-2_%E4%BB%A5%E4%B8%8B%E3%81%A7%E6%B0%97%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%B9%E3%81%8D%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%80heads-up-i18n-1-1-changed-fallbacks-to-exclude-default-local/

解決策は、



```config/environments/production.rb
config.i18n.fallbacks = true
```

となっているところを

```config/environments/production.rb
config.i18n.fallbacks = [I18n.default_locale]
```
にする。
そうすると無事Rails5.2のバージョンをインストールすることができた。
PDFKitで検索した時のDelegateの呼ばれ方

# はじめに
[PDFKit] (https://developer.apple.com/documentation/pdfkit)を使うと、iOSアプリで簡単にPDFビューアを作れるとういことなので、試してみました。このドキュメントでは、PDFKitの検索部分のDelegateについて書きます。

# 開発環境
- Xcode: 11.2
- iOS: 13.2

# PDF検索とDelegate
PDFKitを使ったPDF内の検索は、同期型の`findStrings()`と非同期型の`beginFindStringfindString()`があります。検索時にいくつかのDelegateが呼ばれるようなので、どのような順番で呼ばれるか試してみました。検索に時間がかかる時など、非同期で処理を実施したい時には利用できそうです。

Delegateには、以下の３つの種類があります。

- Document単位
- Page単位
- 検索文字列が見つかった場合

それぞれのDelegateの関係は図で書いた方がわかりやすいので、図を貼り付けておきます。

<img width="700" alt="20191106-ios13-pdfkit-delegate.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404406/8982fd3d-82d3-1bc9-25e2-4f825e18818d.png">


# 参考文献
- [PDFKit(APPLE公式)] (https://developer.apple.com/documentation/pdfkit)
- [PDFDocumentDelegate(APPLE公式)]
(https://developer.apple.com/documentation/pdfkit/pdfdocumentdelegate)
Jetson Nanoの配布可能イメージを作成する

# 概要

最初に触ったLinuxだったのもあってUbuntuベースのJetson Nanoはラズパイより自分にとってとっつきやすく、気軽に使えるLinuxマシンとして遊んでます。

そんなJetson Nanoのバックアップ、dd使っている人が多い様ですが、リスクの高いコマンドなのでいつかやらかしそうで怖い…。

公式の[JetCard](https://github.com/NVIDIA-AI-IOT/jetcard)みたいにEtcherで焼けるイメージを作成すれば安心だし、ホストPC持ってない人に配布したりも出来るよ!ということで手順です。

sdkmanagerが使えるホストPCが必要で、JetPack 4.2.1で検証しています。

# 必要なファイルを調達する

イメージを作成するのにsdkmanagerの内部スクリプトを利用するので[公式サイト](https://docs.nvidia.com/sdk-manager/install-with-sdkm-jetson/index.html)等を参考にホストPCからsdkmanagerでビルドします。(JetsonNanoは繋がなくてOK、フラッシュの時点でキャンセルしてください)

# ビルドスクリプトを実行

ビルドディレクトリ内にcreate-jetson-nano-sd-card-image.shという物があり、それが同ディレクトリのrootfs内をルートパーティションとしてイメージを作成してくれます。そのルートパーティションを入れ替えてカスタムイメージを作ろうと言う訳です。

そのまま使っても良いんですが、ビルドの邪魔になる/ビルドでファイルを消される恐れがあるので必要な所だけ分離します。その上でrootfs内を削除、お持ちのSDカードのルートパーティション内を丸写しします。通常のJetson Nanoならファイルシステムとして読めるパーティションはルートパーティション1つだけのはずなので、ホストPCにSDカードを差せば自動認識すると思います。

また、初期起動時にルートパーティションを自動拡張してくれる便利なスクリプトがデフォルトでは入っているのですが、このスクリプトは成功時に自己削除を行うため、カスタムイメージ作成時に補充する必要があります。

以下の手順で~/nano_sd_image/MyNano.imgというイメージが作成されます。最終行のオプション-sはdfコマンド実行時に表示される使用済み容量よりも大きい値を指定しておきましょう。

```
(必要なファイルの分離)
$ mkdir ~/nano_sd_image
$ cd ~/nano_sd_image
$ sudo cp -ra ~/nvidia/nvidia_sdk/JetPack_4.2.1_Linux_GA_P3448/Linux_for_Tegra/. ./

(自動拡張スクリプトの退避)
~/sudo cp rootfs/etc/systemd/nvresizefs.sh ./
~/sudo cp rootfs/etc/systemd/nvresizefs.service ./ 

(rootfs内の削除)
$ sudo rm -rf ~/nano_sd_image/rootfs/*

(SDカードを差してNanoのデータのコピー)
$ df -BG
Filesystem     1G-blocks  Used Available Use% Mounted on
:
/dev/sdb1            59G   16G       41G  28% /media/<ユーザ名>/<デバイス名>
:
$ sudo cp -ra /media/<ユーザ名>/<デバイス名>/. rootfs/

(自動拡張スクリプトの補充)
$ sudo cp nvresizefs.sh rootfs/etc/systemd/
$ sudo cp nvresizefs.service rootfs/etc/systemd/system/
$ sudo ln -s /etc/systemd/system/nvresizefs.service rootfs/etc/systemd/system/multi-user.target.wants/nvresizefs.service

(イメージの作成)
$ cd ~/nano_sd_image
$ sudo ./create-jetson-nano-sd-card-image.sh -o backup.img -s 17G -r 200
```

これでEtcherで焼けるイメージが現在のディレクトリにbackup.imgとして生成されます。


# あとがき

後は[この記事](https://proc-cpuinfo.fixstars.com/2019/06/nvidia-sdk-manager-on-docker/)を参考にしてDocker内で完結させれば完璧かも。

このTipsを使ってみなさんの素晴らしいJetson Nano環境を公開してください…
wordpress singlepage 画像、タイトル、本文取得

アイキャッチ画像

```php:single.php
アイキャッチ画像のURLを出力
the_post_thumbnail_url( 'medium' );

アイキャッチ画像のURLを取得
get_the_post_thumbnail_url( get_the_ID(), 'medium' );
　取得して出力する場合(echoをつけることで出力が可能)
　echo get_the_post_thumbnail_url();
```

記事の投稿タイトル

```php:single.php
記事のタイトルを出力
<?php the_title(); ?>

wordpressループ内で使用する　タイトルのみを一覧表示例
<?php if ( have_posts() ) : ?>
  <?php while ( have_posts() ) : the_post(); ?>
      <h2><?php the_title(); ?></h2>
  <?php endwhile;?>
<?php endif; ?>

タイトルのURLを取得
・タグなどを含めて取得したい場合
　<?php $title = the_title( '', '', false ); ?>
・引数を指定しない場合、現在の投稿タイトルを返す
　<?php $title = get_the_title(); ?>
```

記事の本文

```php:single.php
本文を出力する
<?php the_content(); ?>

記事のタイトルと本文を出力するループで　一覧表示例
<?php if ( have_posts() ) : ?>
  <?php while( have_posts() ) : the_post(); ?>
      <h2><?php the_title(); ?></h2>
      <p><?php the_content(); ?></p>
  <?php endwhile;?>
<?php endif; ?>
```
【C#, log4net】log4netを使う

やり方をよく忘れるので記録。健忘症どころじゃない。
今回はロガーの初期化（設定読み込み）とロガーインスタンス取得に的を絞るため、設定ファイルの詳細については書かない。

#環境
・IDEはVisual Studio 2017を使用

##1. NuGetでlog4netをインストールする
ソリューションエクスプローラでプロジェクトを右クリックし「NuGetパッケージの管理」を選択する。NuGetからlog4netを検索してインストールする。
　※この時の最新版は2.0.8でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/e1dacfae-564c-d4d9-5f25-0d83667a64e9.png)

##2. プロジェクトにlog4netの設定ファイルを追加する
今回はプロジェクト直下に配置する。
ソリューションエクスプローラでプロジェクトを右クリックして「追加」→「新しい項目」を選択し、開いたダイアログで「アプリケーション構成ファイル」を選択log4net.configという名前でファイルを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/6f84efe6-1c83-10d1-c136-4a7c2f1c00d2.png)

##3. log4netの設定ファイル(log4net.config)の中身を記述する
設定の書き方は下記のサイトが参考になる↓
　・[オープンソースのロギング・サービス「log4net」を使う](https://www.atmarkit.co.jp/ait/articles/0712/25/news121_2.html)
　・[[log4net] log4netの設定](https://blog.hiros-dot.net/?p=5461)
　初めてロガーを使う方は、最初はサイトの設定ファイルを丸コピして動作確認し、それから独自の設定に変えるようにしたほうがベターだと思われる。
　

##4. log4net.configのプロパティを変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/d70cc951-1602-e659-98c7-9a1e2b08abf5.png)
ソリューションエクスプローラでlog4net.configをクリックしてプロパティを表示させ、下記のように変更する。
　・「ビルドアクション」：なし
　・「出力ディレクトリにコピー」：新しい場合はコピーする
　2つ目の設定をしないと「エラーはでないのにログが全然吐かれない!」という事態が起きるので注意。


##5. AssemblyInfoにlog4netを初期化するコードを記述する
　・AssemblyInfo.csファイルを開く(居場所は下の画像を参照)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/0e578327-c9eb-aa7e-712e-cbd9c9b08a60.png)

AssemblyInfo.csに下記の初期化コードを追記する
　※ConfigFile = にはlog4netの設定ファイルの相対パスを指定している。今回設定ファイルはプロジェクト直下にあるためファイル名の頭に何もくっつけてない。

```cs:AssemblyInfo.cs
[assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile = "log4net.config")]
```

ちなみに初期化は任意のクラスでできる。クラスのフィールドに下記のようにして書けばそこに制御が移った時に初期化が行われる。
ただこの場合はロガーを使用する前に初期化が済んだ状態になるよう、処理の順序に気を付ける。

```cs:XXXXX.cs
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config"));
```


　
##6. ロガーインスタンスを取得する
ロガーを使用するクラスのフィールドに下記のコードを書く。

```cs:XXXXX.cs
private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
```
GetLoggerメソッドでロガーインスタンスを取得するが、そのときに自身の型（正確に言えばこのメソッドの呼び出し元が宣言されているクラス）を渡し、自身がどこのクラスかを教えている。


##7. ロガーインスタンスを使ってログ出力する
ログレベルに応じたメソッドを用い、出力したい文字列を引数に渡す。
try-catch句で使えば第2引数にExceptionオブジェクトを渡してスタックトレースを出力する事も可能。

下記はサンプル

```cs:XXXXX.cs
            _logger.Debug("デバッグ用");
            _logger.Info("インフォメーション用");
            _logger.Warn("警告用");
            _logger.Error("エラー用");

            int result = 50;
            _logger.Debug($"結果は{result}です。");

            try
            {
                 hogeFile.Close();
            }
            catch (Exception e)
            {
                _logger.Warn("例外が発生しました。", e);
            }

```

　
##自身がはまった時に確認したポイント
低レベルなことではまってますがご参考までに。
・出力したいログと設定ファイル(log4net.config)のログレベルの設定はマッチしているか？
　自身が出力したいレベルより高いレベルを設定していないかな・・・
・log4net.configファイルのプロパティ「出力ディレクトリにコピー」は「コピーしない」になっていないか？

 
##その他注意点
ロガーインスタンスを取得するコードはフィールドの一番上に書く。
というのも、ログ出力は色々なタイミングで行うであろうものなので、その準備はクラス初期化時の最初に終わらせた方が良い。


##log4netについて参考にさせて頂いたサイト
・log4netの処理について深堀したいときに参考にさせて頂いた
　[きなこもち.net](https://www.kinakomotitti.net/entry/2018/01/22/211703)
バイオインフォにおける環境構築についての雑感

# はじめに
バイオインフォにおける環境設定は面倒だなあ、と思っている僕が、遺伝研の環境に出会って感銘を受けるまでを書いたミニストーリーです。
Galaxyの目指したあるべき姿として、「いろんなツールが楽に入れられる」だと思うんです。
結局、まあまあGalaxyでも面倒だったりするわけなんですが。。。

# きっかけ
某研究室にバイオインフォの講義をするお仕事のサポートとして、
研究室のサーバに基本的なツールを20個くらいインストールしました。
バイオインフォ系のツール、インストールのやり方もバラバラで困りますよね。
（同僚がインストールスクリプト作ってくれたので、いちいちコマンドは打ちませんが）

例として、FASTQCとMACS2の例を挙げておきます。
インストールとしては簡単な方ですけど、JavaとかPythonが絡むので、サーバ全体を気にしつつインストールすることになりますね。

## FASTQCのインストール手順
- （前提）aptでcurlのインストール
- aptでdefault-jreのインストール
- fatsqcのダウンロード（zipファイル）
- zipを解凍して、適切な場所に配置し、実行用のファイルにパスを通す
    - （全員が使えるようにするなら`/etc/profile`などに書いておく）

## MACS2のインストール手順
- （前提）python, python-dev, libpython-dev, python-pip
- pip install でnumpy, MACS2を入れる
    - Python2がデフォルトの環境なら「pip3」

# 遺伝研にて
別の業務で、遺伝研のスパコンに社内で作ったシェルスクリプト（複数のツールを順次動かすパイプライン）を動かすことになりました。
同じように環境設定しようと思いましたが、あれ？何もすることなくね？
（気づくまでしばらく時間かかりましたが。。。）

## 遺伝研の環境の特徴
- Singularityが入っている。
- `/usr/local/biotools/` 以下に基本的なSingularityイメージが複数のバージョンで置いてある
- 自身でイメージを作って持ってくることも可能なので、好き放題どんなコマンドでも動かせる。

## FASTQの実行ファイル
下記のような「fastqc」ファイルを作って、実行権限をつける。qloginして実行すればOK

```
#!/bin/sh
module load singularity
singularity exec /usr/local/biotools/f/fastqc\:0.11.5--pl5.22.0_2 fastqc $@
```
 
## 終わりに
バイオインフォって無茶苦茶いっぱいツールを使うくせに、インストールするだけで敷居が高いんだよなあ、と思ってました。Dry解析教本でも結構細かく説明されてます。
あと、Python2でしか動かないツールがあったりと、ミドルウェアについての制約条件も結構面倒。
そうなると、仮想環境ってのは便利です。が、Dockerはroot権限で動きやがったりするので、システム管理者としては胃が痛い。。。その点、root権限が不要なのは、Singularityの良さだと思います。
遺伝研スパコンのようにいろんなバージョンのイメージを置いておけば、過去のバージョンのコマンドを持ち続けることもできますし、再現性という観点でも素晴らしいと思います。リソースが潤沢だからこそ出来ることですが。
深い位置のプロパティにいきなり代入する

PHPで深い位置のプロパティに、いきなり値を代入したいが
次のようなコードでは、警告が発生してしまう。

```php
$a = new stdClass;
$a->b->c = 1; //代入はできるが警告が出る
```

マジックメソッド``__get()``を利用することで、目的が達成できた。

```php
class exClass{
    function __get($name){
        $this->$name = new self;
        return $this->$name;
    }
}

$a = new exClass;
$a->b->c = 1; //成功
```

ただし問題があって、未定義のプロパティをgetした場合は、exClassオブジェクトが返ってくる。
AndroidのTabLayout(Material Design)の文字をカスタムViewを使わずにカスタマイズする

※一部の古いOSバージョン・端末では正しく適用されない場合があるので、それらをサポートしている場合は注意してください。

`com.google.android.material.tabs.TabLayout`の文字装飾（太字にする、色を変える、サイズを変えるなど）はSpannableを使うことで、カスタムViewにしなくてもある程度はカスタマイズできます。Spannableを使うので、テキストの一部だけ文字サイズを変えるなどの装飾をすることもできます。

# すべてのタブの文字をカスタマイズする

すべてのタブで統一した文字装飾を実装する場合は、`PagerAdapter.getPageTitle`をOverrideして`SpannableString`を返すとカスタマイズできます。

```kotlin
    //タブの曜日のテキストだけ小さくする
    override fun getPageTitle(position: Int): CharSequence? {
        return dates[position].let {
            val date = it.atJST().toLocalDate()
            SpannableStringBuilder().append(
                DateTimeFormatter.ofPattern("d", Locale.ENGLISH).format(date)
            ).append(
                DateTimeFormatter.ofPattern(" E", Locale.ENGLISH).format(date),
                RelativeSizeSpan(0.7f),
                Spannable.SPAN_INCLUSIVE_EXCLUSIVE
            )
        }
    }

```

`SpannableString`については以下記事がわかりやすいです。

[Spantastic text styling with Spans](https://medium.com/androiddevelopers/spantastic-text-styling-with-spans-17b0c16b4568)

# 選択中のタブの文字だけカスタマイズする

選択中のタブの文字だけ装飾するには、`Tablayout.addOnTabSelectedListener`で、textを`SpannableString`にすればカスタマイズできます。

```kotlin

　　//すでに適用されている装飾を残しつつ、選択中のタブだけ太字にする
    Tablayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            private val normal = StyleSpan(Typeface.NORMAL)
            private val bold = StyleSpan(Typeface.BOLD)
            override fun onTabReselected(tab: TabLayout.Tab?) {
            }
            override fun onTabUnselected(tab: TabLayout.Tab?) {
                tab?.also {
                    it.text?.also { text ->
                        val span = if(text is SpannableString) text else SpannableString(text)
                        span.removeSpan(bold)
                        span.setSpan(
                            normal,
                            0,
                            text.length,
                            Spannable.SPAN_INCLUSIVE_INCLUSIVE
                        )
                        it.text = span
                    }
                }
            }
            override fun onTabSelected(tab: TabLayout.Tab?) {
                tab?.also {
                    it.text?.also { text ->
                        val span = if(text is SpannableString) text else SpannableString(text)
                        span.removeSpan(normal)
                        span.setSpan(
                            bold,
                            0,
                            text.length,
                            Spannable.SPAN_INCLUSIVE_INCLUSIVE
                        )
                        it.text = span
                    }
                }
            }
        })
```

# 参考リンク

[Tab Layout - Material Components for Android](https://material.io/develop/android/components/tab-layout/)

[TabLayoutでいい感じにアイコンをつけたい時のメモ - 言いたいことはそれだけか](http://muumuutech.hatenablog.com/entry/2019/02/02/232805)

[Custom views at TabLayout with highlighted text style at the selected tab](https://medium.com/@pjonceski/custom-views-at-tablayout-with-highlighted-text-style-at-the-selected-tab-7cb6389a633)
Pythonメモ

# 概要
今回の勉強会ではPythonを使っていくつかのプログラミングを行うというものだった

# 勉強内容
今回の講義で挑戦した問題は以下の4問

[9×9](https://atcoder.jp/contests/abc144/tasks/abc144_a)
[curtain](https://atcoder.jp/contests/abc143/tasks/abc143_a)
[Odds of Oddness](
https://atcoder.jp/contests/abc142/tasks/abc142_a)
である。
以下ではこれらの問題を実際に解いてみ個人的にjavaやC言語と違うと感じた点を記す

# 9×9
この問題ではinput関数の中で数値を扱うことを主に問題を解いていった。
Pythonは今まで学んできたjavaやC言語とは異なり
`a = 1`
と入力するだけで出力が`1`となる点がとても便利な点だと使って思った
また1つの行に複数の数値を入力する際は`map(int,input().split())`を使う
# curtain
この問題ではA - 2Bの差が0以下だった場合は窓が完全に覆われるので
`if [条件式]:
  [条件式がtrueの時に行う処理]
else:
   [条件がfalseの時に行う処理]`
を用いれば簡単に解くことができた。
If文のjavaやC言語との違いは条件式を記入した後、：が必要になり、処理内容を記入する際は改行して記入するという点である。

# Odds of Oddness
この問題では入力したNの数が偶数だった場合N以下の奇数はN/2個でNが奇数だった場合は、N以下の奇数はN/2+1個になる点に着目して先程用いたif文を用いれば解くことができる。ここでは新しく剰余と除算を使った。
`x % y `でx÷yの剰余が
`x/y`でx÷yの商を求めることができる
この問題で自分は剰余が0だったときは偶数で0でないときは奇数という場合分けをして解いた。
gitgubにリポジトリ作成し、ユーザー共有する方法

- 基本的には`private`設定にする。

- コマンドで、リポジトリ作成したいディレクトリに移動する（cd）。

- 下記コマンドを実行
`git init
git add *
git commit -m "first commit"
git remote add origin git@github.com:自分のユーザー名/リポジトリ名（git上と合わせる）
git push -u origin master
`

- Settings -> Collaboratorsから、共有したいユーザーを追加
Arch Linuxのアップデート失敗時の対処法

# はじめに
Arch Linuxはローリング・リリースを採用したLinuxディストリビューションです．
それにより，時々，アップデートに失敗することがあります．
本記事では，アップデート失敗時のオーソドックスな対処法を3つの場合に分けて紹介します．

# Arch Linux全体で問題が起きている場合
公式リポジトリ側の都合でアップデート前に手動で作業が必要な場合があります．
そのときは，[Arch Linux公式サイトの最新ニュース](https://www.archlinux.jp/)に対処法とともに書き込まれます．

# 久しぶりにアップデートをした場合
半年間アップデートをしていないPCなどでアップデートをかけると高確率で失敗します．
これはアップデートに使う鍵が更新されていないことが原因です．
次のコマンドを実行することで鍵が更新され，アップデート出来るようになります．

```bash
$ sudo pacman -Sy archlinux-keyring
```

# AUR (Arch User Repository) のパッケージをインストールしている場合
公式リポジトリ側のアップデートの影響でAURパッケージの依存関係が満たされなくなることがあります．
アップデート失敗時のエラーメッセージにライブラリ名が含まれている場合は，この可能性が高いです．

解決策としては以下の2通りです．
1. 不要なAURパッケージを全てアンインストールし，アップデートを試みる．
2. エラーメッセージを参考に検索をして，問題のパッケージを特定する．

TIPS: 英語で検索すると，海外フォーラムで同じ問題に悩まされている人の投稿が見つかることがあります．運が良ければ，そこに解決策が載っています．

# まとめ
本記事ではArch Linuxのアップデート失敗時のオーソドックスな対処法を3つ紹介しました．
皆さんのトラブル解決の参考になりましたら幸いです．

# 参考
- [Arch Linux JP Project](https://www.archlinux.jp/)
- [pacman-key--ArchWiki](https://wiki.archlinux.jp/index.php/Pacman-key)
Python一時間触ってみて

 - Pythonはスペースキー5回でインデントができる、便利
 - inputで簡単に文字入力ができるが、複数入力の場合は
```
map(int,input.split())
```で行う、少し面倒
また、改行で標準入力をする時はrange関数を用いる
```
int(input()) for i in range(5)
```
 - 基本的なif文やfor文は他の言語とあまり変わりはないが、for文はrangeを使うと少し複雑なものでも一行で定義できるのでここすごく好き、便利
macOS CatalinaでAzureVPNに接続するとダイアログ「予期しないエラーが起きました。」が表示される

日本語の情報がなかったのでメモ。

# 事象
macOSをMojaveからCatalinaへバージョンアップした。

その後、macOS標準のVPNクライアントでAzureVPNへ接続を試みたところ、
ダイアログ「予期しないエラーが起きました。」が表示されて接続できない状態となった。

![20191106_error_dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371702/0ad51138-257d-f8dc-b406-3bab3e975b6a.png)

VPNの設定はバージョンアップ前から存在していて、バージョンアップ前は正常に接続できていた。

以下のページに従って新たにVPN接続の設定を行なったが、エラーは解消しなかった。
[ネイティブ Azure 証明書認証の P2S 構成のための VPN クライアント構成ファイルを作成およびインストールする](https://docs.microsoft.com/ja-jp/azure/vpn-gateway/point-to-site-vpn-client-configuration-azure-cert)

# 原因
表面的な原因は、macOSをCatalinaへバージョンアップしたこと。
根本的な原因は不明。

# 対策
Microsoft Developer Networkの以下のページを参考にVPN設定を修正する。
[MacOS Catalina IKEv2 VPN Client to Azure VPN Gateway Incompatibility](https://social.msdn.microsoft.com/Forums/en-US/ed4b9407-5a6a-4155-bc94-7353bc76296d/macos-catalina-ikev2-vpn-client-to-azure-vpn-gateway-incompatibility?forum=WAVirtualMachinesVirtualNetwork)

* macOSの「ネットワーク」画面を開く
* ネットワーク一覧から接続できなくなったVPN設定を選択する
* 「認証設定…」ボタンを押下する
* 「認証設定」プルダウンを「証明書」から「なし」へ切り替えて「OK」ボタンを押下する
* 「適用」ボタンを押下する

![20191106_vpn_dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371702/d7b1cb0d-39fd-1025-536c-8625418177e1.png)

# 備考
本件がバグであるなら、将来的に改善される可能性はある。
その際は、改めて設定の変更が必要になるかもしれない。
Redmineのバックアップ環境を構築する

#概要
今までは細々と数名でRedmineを使用していたが社内全体でRedmine使用する運びになり、
そのための運用ルールの策定やバックアップルールについて考えることになったのでメモ

#バックアップ方法
・日次でRedmine添付データ（files）、及びデータベースのダンプファイルを取得し
　バックアップ用サーバに転送する。
・バックアップデータは世代管理を行う。
・リストア時にはAnsibleにて新たにRedmineサーバを構築し、バックアップデータより復元を行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294638/043d60a5-72d5-1f31-cb32-11e589c876e4.png)


#環境構築
##1. SSHの自動化
rsyncで同期処理をかける際に、パスワード使用せずログインできるよう
公開鍵認証を使用してSSHログインを自動化します。
Redmineサーバでの作業は、postgresユーザで実施

```
$ssh-keygen -t rsa
Enter file in which to save the key: (鍵の保存先が表示される)　# Enterを入力
Enter passphrase (empty for no passphrase): # Enterを入力
same password: # Enterを入力
$scp .ssh/id_rsa.pub ユーザ名@バックアップサーバホスト名:~/.ssh

```
バックアップ用サーバにて、送られてきた公開鍵の使用設定を行います。

```
#バックアップ用サーバで実施
$cd ~/.ssh
$mv id_rsa.pub authorized_keys
$chmod 600 authorized_keys
```


##2. バックアップ用ディレクトリ、シェルスクリプトの作成
シェルスクリプトを作成する前に、mkdirコマンドにて下記のディレクトリを
予め作成しておきます。

・Redmineサーバ
/home/postgres/redmine_backup
（postgresユーザのホームディレクトリにredmine_backup）

・バックアップサーバ
/backup/redmin_backup

次にバックアップを行う為のシェルスクリプトを
Redmineサーバのpostgresユーザホームディレクトリに作成します。

```backup.sh
#!/bin/sh
pg_dump -U postgres redmine > ~/redmine_backup/db_`date +%Y%m%d%k%M%S`.dump
tar -cvzf ~/redmine_backup/files_`date +%Y%m%d%k%M%S`.tgz /var/lib/redmine/files
find ~/redmine_backup -name "db_redmine_*" -mtime +30 -exec rm {} \;
find ~/redmine_backup -name "files_*" -mtime +30 -exec rm {} \;
```

##3. シェルスクリプトの実行
スクリプトに実行権限を付与し、実行

```
$chmod +x redmine_backup.sh
$./redmine_backup.sh
```

filesとDBのdumpファイルがバックアップサーバに転送されているはずです

##4. 自動バックアップの設定
最後に、毎日決まった日時に自動でバックアップしてくるように
Redmineサーバにてスクリプトの自動起動設定を行います。

```
$crontab -e 
```

viが立ち上がったら以下を記載

```
00 23 * * * /作成したシェルスクリプトまでのパス/redmine_backup.sh
```

上の記述だと毎日23:00にバックアップを実行する設定になっています。
（cronについては[こちら](https://qiita.com/onomame/items/71646c5517a39bcd01cc)を参照）

必要に合わせて設定変更してみてください。
以上でバックアップ環境の構築は終了です。

#注意点
Redmineサーバ、バックアップ用サーバ共にrsyncコマンドを使用できるようにする必要がある。
インストールされていない場合はyumコマンドにてインストールを行う。
[Python3] UDP でデータを送受信する方法

# 環境
python 3.x
OS は問わない

# 送信側
```python:udpsend.py
from socket import *

## UDP送信クラス
class udpsend():
    def __init__(self):

        SrcIP = "127.0.0.1"                             # 送信元IP
        SrcPort = 11111                                 # 送信元ポート番号
        self.SrcAddr = (SrcIP,SrcPort)                  # アドレスをtupleに格納

        DstIP = "127.0.0.1"                             # 宛先IP
        DstPort = 22222                                 # 宛先ポート番号
        self.DstAddr = (DstIP,DstPort)                  # アドレスをtupleに格納

        self.udpClntSock = socket(AF_INET, SOCK_DGRAM)  # ソケット作成
        self.udpClntSock.bind(self.SrcAddr)             # 送信元アドレスでバインド

    def send(self):

        data = "Hello"
        data = data.encode('utf-8')                     # バイナリに変換

        self.udpClntSock.sendto(data, self.DstAddr)     # 宛先アドレスに送信

udp = udpsend()     # クラス呼び出し
udp.send()          # 関数実行
```
- socket の引数の AF_INET は IPv4 用。AF_INET6 は IPv6 用
- SOCK_DGRAM は UDP 用。TCP の場合は SOCK_STREAM
- DstAddr でバインドしなくてもデータを送信できるが、バインドしないと送信元アドレスが固定されない
    - 受信側で送信元を指定する場合は設定しておいたほうが吉
- sendto するときにデータをバイナリに変換する必要がある
- "127.0.0.1" は自分自身のIPアドレスなので、任意に変更すると異なる機器間で通信が可能


# 受信側
```python:udprecv.py
from socket import *

## UDP受信クラス
class udprecv():
    def __init__(self):

        SrcIP = "127.0.0.1"                             # 受信元IP
        SrcPort = 22222                                 # 受信元ポート番号
        self.SrcAddr = (SrcIP, SrcPort)                 # アドレスをtupleに格納

        self.BUFSIZE = 1024                             # バッファサイズ指定
        self.udpServSock = socket(AF_INET, SOCK_DGRAM)  # ソケット作成
        self.udpServSock.bind(self.SrcAddr)             # 受信元アドレスでバインド

    def recv(self):
        while True:                                     # 常に受信待ち

            data, addr = self.udpServSock.recvfrom(self.BUFSIZE)
                                                        # 受信
            print(data.decode(), addr)                  # 受信データと送信アドレス表示

udp = udprecv()     # クラス呼び出し
udp.recv()          # 関数実行
```
- 受信側では受信するアドレスでバインドして受信を待つ
    - 送信アドレスを指定したりせず全てを受け入れる
- print で送信したデータと送信元のアドレスを表示する
- バッファサイズはデータサイズによって変更してほしい

# 実行方法
コンソールを２つ起動。
cd ~~ で .pyファイルがある場所へディレクトリ移動。
### 受信側(コンソール①)
```
python3 udprecv.py
```
これで受信待ち状態になる。
### 送信側(コンソール②)
```
python3 udpsend.py
```
"Hello" を１回送信する。

# 実行結果(コンソール①)
```
Hello ('127.0.0.1', 11111)
```

# まとめ
通信プロトコルの一つであるUDPでデータを送受信することができた。
個人的にひっかかったのは、アドレスをバインドする意味が始め分からなかったところである。
送信側で送信先を指定しないと、、と思って送信先アドレスでバインドするとうまくいかなかった。
要するに、間違っていたのは
「ソケットをバインドする」＝「自らのアドレスで固定する」
というところだった。

新卒、勉強不足。

解釈に間違いがあれば指摘してほしい。
SwiftUIでプレビューがUnknown preview provider "ContentView_Previews"エラーとなる

![macOS-10.15.1](https://img.shields.io/badge/macOS-10.15.1 -blue) ![Xcode-11.2](https://img.shields.io/badge/Xcode-11.2 -blue) ![iOS-13.2](https://img.shields.io/badge/iOS-13.2 -blue)
小ネタですがハマってしまったので誰かの参考になれば。

## 現象

ビルドは通りますし、実行したら実機で動きますが、
プレビューがエラーで表示されません。

![ 2019-11-06 10.09.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190739/3b367653-b0db-6800-a576-b54752d59aab.png)

## 原因

Display Nameが日本語なのが原因でした。
英数字のみにしたら直りました。

![ 2019-11-06 10.13.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190739/f8696525-f5ba-6a32-f40a-0ef3d8ed543a.png)

## 回避策

そうは言ってもアプリ名は好きに付けたいですよね。

Display Nameは英数字のみにしつつ、
Info.plistのBundle display nameを好きな名前にすることでこの問題を解決しました。

![ 2019-11-06 10.19.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190739/b2e6cf6f-1735-8cdf-d566-34ef96a98854.png)