OmniAICreator/Qiita-1.07M huggingface dataset:
ローカルネットワークにMattermostを構築した

## Mattermostとは

SlackライクなOSS版チャットツールです。
お仕事の都合上クラウドにデータが保存されるのは心配、という方におすすめです。
<img width="1010" alt="スクリーンショット 2019-12-12 17.00.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202428/c2884031-29c2-d766-46a8-cb02c79a22e2.png">

## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/mattermost) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

`docker-compose.yml`ファイルと、volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。

こちらの記事も見てください。
[掃除当番つぶやきボットを作ってみた](https://qiita.com/radiance1104/items/5eb44ff0302ccab20c8f)
Linuxを初めて学習するならこれをやろう！

#対象者
Linuxを業務で使うことになった
何から勉強すればいいかわからない
という方に見ていただければと思い投稿しました。
不明点があれば、コメントしてください。
適宜編集していきます！

##前提として
自由にLinuxを操作ができる環境があること。
OSのインストールについては、たくさん記事があるので割愛します。
（自宅よりもクラウド上に構築がおすすめです。）

##Webサーバを構築してみよう
これが一番Linuxのことを色々と学習できると思っています。

- 一般ユーザ(限られたコマンドのみ実行できるユーザ)saitoでログイン
- saitoユーザでログイン出来たことを確認

```shell
$ id
uid=1000(saito) gid=1000(saito) groups=1000(saito)
```

---
補足：操作できる一般ユーザがいなかった場合

```shell
# useradd saito
# passwd saito
（PWは何でもOK。画面に出力はありませんので、二回入力します。）
```
---

- rootユーザに切り替え

$ から # にプロンプトが変わります。

```shell
$ su -
Password: (rootのPWを入力)
# 
# id
uid=0(root) gid=0(root) groups=0(root)
```

-  Webサーバに必要なパッケージがインストールされているかを確認

パッケージとは、ソフトウェアだと思ってもらえばOKです。
今回はApache(httpd)を想定しています。
以下を実行して出力がなければ、未インストールだということがわかります。

```shell
# rpm -qa | grep httpd
```

---
補足：httpdをインストールする方法
rpmとyumの違いは機会があれば投稿します。

```shell
# rpm -ivh httpd*
または
# yum -y install httpd
```
---

- ブラウザを開いて、アクセスしてみましょう

ブラウザのURLに「http://localhost」と入力し実行します。
HTTPサービスが起動出来ていないため、エラーが出ます。

- HTTPのサービスの状態を確認、起動

```shell
# systemctl status httpd
　　　：
 Active: inactive (dead)
　　　：
# systemctl start httpd
　　　：
 Active: active (running)
　　　：
```

- ブラウザを開いて、再度アクセスしてみましょう

ブラウザ上でF5キーなどで更新をすると、テストページが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440776/655590b2-4723-3db0-3536-2b8ef8777142.png)

---
おまけ：自分でHTMLファイルを作ってみる

```shell
# vi index.html
--ここから--
<html>
<head>
 <title>Test Page</title>
</head>
<body bgcolor=skyblue>
 <h1>hello world</h1>
</body>
</html>
--ここまで--
```
- 作ったHTMLを確認

```shell
# ls
（index.htmlがあることを確認）

# cat index.html
（編集が必要になった場合は、vi index.htmlを実行）
```

- 作成したHTMLファイルをコピー、確認

```shell
# cp index.html /var/www/html
# ls /var/www/html
```

-ブラウザを開いて、再度アクセスしてみましょう
自分で作ったHTMLが確認できます！

---

#まとめ
Webサーバの構築をすることで
- ログイン
- ユーザ切り替え
- ファイル操作
- ファイル編集
- パッケージ管理
- サービス起動
- （プロセス）
などをたくさんのことを学習出来ます。
python初心者がサッカーのデータで遊んでみた

#目的
今回はpython初心者がデータ分析の勉強のため難しくなく、
興味を持ちやすいテーマ！サッカー（勝手なイメージ）であれこれしてみます

特に、個人的にはボールの支配率が高いチームは強いチームという認識がありますが
そういうチームは上位にいきやすい？っていうのも検証したいと思います


#データの準備
サッカーのデータを探してたところ、kaggleに2018年ロシアW杯のデータがありました。
https://www.kaggle.com/mathan/fifa-2018-match-statistics/version/20# からcsvをダウンロードする。

#データの概要

```Python
import pandas as pd
data = pd.read_csv('/Users/hwang.taejun/myworkspace/FIFA 2018 Statistics.csv')
print(data)
```
すると、
![スクリーンショット 2019-12-11 18.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535765/903257b6-8846-4650-8542-4e171af054d1.png)

W杯の開幕戦から決勝までの試合データが入ってます
２行ずつ1試合になってるので前処理が必要かも?

#中身をみてみよ

```python
print(data['Team'])
```
![スクリーンショット 2019-12-11 18.47.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535765/9d5094a4-7f66-f066-f627-9d67069a1fad.png)

```python
print(data['Goal Scored'].mean()) #ゴールの平均
1.3203125
print(data['Goal Scored'].sum()) #ゴールの合計
169
```
dataframeの中でカラムを指定するとそのカラムの数値がわかります
全試合のゴールの合計は169って言ってますね

##チームごと
まず、優勝したフランスのデータだけ絞ってみます。indexもチームに変えましょう

```python
data.set_index('Team').loc['France'].mean()
```
![スクリーンショット 2019-12-11 19.01.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535765/a1c98571-3535-ebc4-2032-66c28252bb22.png)
フランスだけの結果がかえってきました
データをみると１試合平均２ゴール、ボール支配率は平均約48バーセントですね

そうしたら、チームごとだしてみましょう

```python
team = []
for nation in data.set_index('Team').index:
    if nation not in team:
         team.append(nation)
    team_summary = {}
    for nations in range(len(team)):
         team_summary[team[nations]] = data.set_index('Team').loc[team[nations]].mean()
```
チームが重複している形なので除外しましょう（１試合に２行になってるから）
`data.set_index('Team').index`の重複するチームを除外するfor文を回します
そうすると32チーム揃えることができる

重複除外後、チームごとのデータがわかるfor文を回すと
結果、チームごとのデータがかえってきます
![スクリーンショット 2019-12-11 20.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535765/0ec5a862-db0e-4e9d-af82-02f1e34f311e.png)



上記の結果を使って
一番ゴールをきめたチームとボールの支配率が一番高いチームとかだしてみました

```python
goals={}
possession={}
for stats in range(len(team)):
    goals[team[stats]] = team_summary[team[stats]][0]
    possession[team[stats]] = team_summary[team[stats]][1]
print(max(goals, key=goals.get))
'Belgium'
print(max(possession, key=possession.get))
'Spain'
```
maxは一番大きい値をだしてくれる。一番ゴールをきめたチームはベルギー
ボール支配率はスペインだそうです！
この二つ以外にもカラム名を使っていろんな結果が見れます


次は気になっていたボールの支配率が高いチームは上位にいきやすいかみてみましょう
上記のdict型の`posseisson`を使って棒グラフでplotしてみると？

```python
import matplotlib.pyplot as plt
values = possession.values()
keys = possession.keys()

plt.bar(keys,values)
plt.show()
```

<img width="712" alt="スクリーンショット 2019-12-12 17.43.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535765/4f488662-756e-c524-9163-ac6049270516.png">
チームごとのボール支配率がかえってきました。

1.トップ10でベスト8に入ったチームは３チームしかない
2.予選落ちのドイツとサウジアラビアがトップ5に入ってる
3.ベスト8に入ったロシア、スウェーデンは30位と28位
4.優勝チームのフランスは32チームの中で20位、３位のベルギーは12位
5.トップ5のスペイン、アルゼンチン、スイスはベスト16で落ちたチーム



ってことはボールの支配率は決勝トーナメントに進出したチームとあまり関係がないように見えますね。以外すぎる...

#さいごに
pythonで分析の練習のために筆者が好きなサッカーのデータであれこれやってみました
コードをみると初心者ってすぐバレると思いますが一通りなんかかきました 笑

このデータでもっと面白い分析ができると思ったけど今回はこれくらいにしておきます・・・
こういう練習を重ねてもっといい記事をまた今度書いてみます！
bluebird.jsのPromise.mapとPromise.mapSeries

# はじめに

この記事は[bluebird.js](http://bluebirdjs.com/docs/getting-started.html)の`Promise.map`と`Promise.mapSeries`について、勉強会で取り上げたものです。

# 1. Promise.mapについて

[Promise.mapの公式ドキュメント](http://bluebirdjs.com/docs/api/promise.map.html)

## 1-1. 概要

**入出力仕様**

```js

Promise.map(array, function, options) -> Promise
```

`map` は第１引数で受け取る配列の各要素について、第２引数でそれを引数にとる非同期関数を **『並列に順番に実行して』**、実行した全ての非同期関数の完了を待つPromiseを返す。  
このPromiseがresolveしたとき、非同期関数の戻り値の結果が**『順番に入った配列』**を返す。ただし **『実行が完了する順番は保証されない』**。

つまり・・・

* 結果の順番は保証される
* 実行を開始する順番は保証される
* 実行が完了する順番は保証されない

また、第３引数に`concurrency`プロパティを渡すと、同時に実行する数を制限できる（デフォルトは制限なし）。

## 1-2. サンプルコード

### 基本的な例

```js

// 非同期的に2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * 2), 1000);
  });
};

const result = await Promise.map( [1, 2, 3, 4, 5], x2 );
console.log(result);
// -> [2, 4, 6, 8, 10]
```

### 実行完了の順番が保証されない例

```js
// 非同期的かつランダムに遅らせて2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    const ms = Math.random() * 1000 // ランダムな遅れ
    setTimeout(() => {
      const res = num * 2;
      console.log(res); // コンソール出力（処理完了）
      resolve(res);
    }, ms);
  });
};

const result = await Promise.map( [1, 2, 3, 4, 5], x2 );
console.log(result);
/*
# コンソール出力
> 10
> 6
> 8
> 2
> 4
# ↑のようなときもあれば

# ↓のようなときもある
> 2
> 10 
> 4
> 6
> 8

# だけどresultの値は必ず順番通りになる
> [2, 4, 6, 8, 10]
*/

```

### concurrencyで同時に実行する数を制限する例

```js
// 非同期的に2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * 2), 1000);
  });
};

const result = await Promise.map([1, 2, 3, 4, 5], x2, { concurrency: 2 }); // 同時に2つ実行
console.log(result);

/*
# 出力
# 1秒後
> 1
> 2
# さらに1秒後
> 3
> 4
# さらに1秒後
> 5
# resultの値
> [2, 4, 6, 8, 10]
*/
```

# 2. Promise.mapSeriesについて

[Promise.mapSeriesの公式ドキュメント](http://bluebirdjs.com/docs/api/promise.mapseries.html)

## 2-1. 概要

**入出力仕様**

```js
Promise.mapSeries(array, function) -> Promise
```

mapSeriesは第１引数で受け取る配列の各要素について、第２引数でそれを引数にとる非同期関数を
**『直列に順番に実行して』**、実行した全ての非同期関数の完了を待つプロミスを返す。  
Promise.mapと殆ど同じだが、唯一の違いは**『実行が完了する順番が保証されること』**。また、直列に実行するため`concurrency`プロパティがない。

## 2-2. サンプルコード

### 実行完了の順番が保証される例

```js

// 非同期的かつランダムに遅らせて2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    const ms = Math.random() * 1000 // ランダムな遅れ
    setTimeout(() => {
      const res = num * 2;
      console.log(res); // コンソール出力（処理完了）
      resolve(res);
    }, ms);
  });
};

const result = await Promise.mapSeries( [1, 2, 3, 4, 5], x2 );
console.log(result);

/*
# 出力
# 直列に実行するため処理が完了する順番が保証される
> 2 
> 4
> 6
> 8
> 10
# resultの値
> [2, 4, 6, 8, 10]
*/
```

# 3. 最後に

`bluebird.js` は便利なヘルパーが多数用意されていてとても便利ですね。非同期処理の実装がとてもラクになります。
Googleで調べるときは検索窓に`bluebird.js`と入れることをオススメします。`.js`をつけないで検索すると・・・。
Wifi経由でadbコマンドを実行しよう（1．Windows編）

# はじめに
　Androidアプリのデバッグといえば
ケーブルでPCとAndroid端末を接続して行うものだと思っていましたが、
Wifi経由でもadbコマンドを実行することが可能です。

# 使用ツール
- Windows PC
- コマンドプロンプト
- Android端末（Wifi接続して、IPアドレスを振っておくこと）
- Wifi環境

# 手順
1. Android端末の開発者モードをONにしてUSBデバッグを可能にする。
2. PC、Android端末ともにWifiに接続。
3. adb接続。
4. adbコマンドを実行。
5. adbを切断。

# 1. Android端末の開発者モードをONにしてUSBデバッグを可能にする。
# 2. PC、Android端末ともにWifiに接続。
手順1、2は略。
# 3. adb接続。
コマンドプロンプトで下記コマンドを実行してadb接続をします。
`:5555`部分は省略可能です。

```
adb connect 123.456.789.012:5555
```
# 4. adbコマンドを実行。

接続している端末の確認

```
adb devices
```
ADBを停止させる

```
adb kill-server
```
ADBを起動する

```
adb start-server
```
複数接続している時。
Wifi接続であれば、複数端末と接続も考えられますよね。

```
adb -s 端末名やIPアドレス コマンド
```
-sオプションで操作対象の端末を選択することが出来ます。

Android端末にログイン

```
adb shell
```

Android端末からログアウト

```
exit
```
# 5. adbを切断する。

```
adb disconnect 123.456.789.012:5555
```
# 参考サイト
[ADBの基本的な操作](https://blog.unsweets.net/2015/01/basic-adb/)
卒業・退職済み利用者宛のメールは転送のみを行う

## 概要

3000人程度の利用者に対するメールシステムを、かれこれ12年間、オンプレミスで運用してきたのですけれど、ついに G Suite に移転することになりました。その間に得たノウハウを、このままロストテクノロジーにするのも惜しいので、過去の作業ログの中から、ある程度汎用性がありそうなトピックを取り出して、公開しようと思います。

近年、卒業・退職した利用者に対して大学からコンタクトをとる必要性[^reason]から、構成員に対して生涯メールアドレスを発行するように、大学本部から要請されるケースが増えています。しかし、卒業・退職した利用者のメールボックスも維持していると、メールボックス用ストレージの残容量が速攻で破綻します。

[^reason]: 例えば、寄付金を募るなど。

そこで、折衷案として、卒業・退職した利用者に対しては、メールの転送のみを行い、メールボックスの提供はしない、という運用を行なってきました。本稿では、そのための設定手順を紹介します。

## 前提

幾つかの前提があります。

* SMTP は Postfix で処理している。
* IMAP/POP3 は Dovecot で処理している。
* ローカルなメールボックスへの配送（Postfix → Dovecot）は、LMTP で行う。
* ユーザによる転送先設定は LDAP に格納されている。

## 設定内容

設定の基本的な方針は、以下の2段階からなります。

1. 全利用者宛のメールを転送またはメールボックスに配送する。
2. メールボックスに配送する時点で、卒業・退職済み利用者宛のメールを破棄する。

これにより、卒業・退職済み利用者については、転送のみを行なって、メールボックスへの配送は行わない、という挙動になります。

### 全利用者宛のメールを転送またはメールボックスに配送する

基本的な設定は、以下の通り。

```conf:/etc/postfix/main.cf
mydomain = example.jp
mydestination = $myhostname, $mydomain
alias_maps = ldap:/etc/postfix/forward.cf
```

転送設定は、各利用者の `mailForward` 属性に格納されているものとします。LDAP サーバから読み込むための設定ファイルを、以下のように用意します。

```conf:/etc/postfix/forward.cf
bind=yes
bind_dn=cn=mailsystem,ou=systems,dc=example,dc=jp
bind_pw=********
server_host=ldap.example.jp
server_port=389
timeout=20
search_base=ou=users,dc=example,dc=jp
scope=sub
query_filter=(uid=%u)
result_attribute=mailForward
```

正しく設定されていれば、以下のコマンドで利用者の転送設定が取り出せるはずですので、確認しておいて下さい。

```shell-session
$ postmap -q alice@example.jp ldap:/etc/postfix/forward.cf
```

ここまでの設定で、まず、全ての利用者（現役の利用者、卒業・退職済み利用者、双方ともに）について、LDAP の設定内容にしたがってメールの転送が行われるようになっているはずです。

なお、メールを転送するだけでなく、メールボックスにも配送を希望する利用者には、以下のように自分自身のメールアドレスも `mailForward` 属性に書いておいてもらう必要があります。

```
mailForward: alice@outside.example.net
mailForward: alice@example.jp
```

### メールボックスに配送する時点で、卒業・退職済み利用者宛のメールを破棄する

まず、`/etc/postfix/main.cf` に以下のように設定します。

```conf:/etc/postfix/main.cf
local_recipient_maps = $mailbox_transport_maps
mailbox_transport_maps =
	ldap:/etc/postfix/active_mailbox.cf
	ldap:/etc/postfix/expired_mailbox.cf
```

現役の利用者宛のメールが LMTP 配送されるように、以下のように設定します。なお、利用者の状態は、各利用者の `accountStatus` 属性に格納されているものとします。

```conf:/etc/postfix/active_mailbox.cf
bind=yes
bind_dn=cn=mailsystem,ou=systems,dc=example,dc=jp
bind_pw=********
server_host=ldap.example.jp
server_port=389
timeout=20
search_base=ou=users,dc=example,dc=jp
scope=sub
query_filter=(&(uid=%u)(accountStatus=active))
result_attribute=uid
result_format=lmtp:imap.example.jp
```

最後の `result_format` パラメータの設定が重要です。ここで、LMTP 配送すること、配送先が `imap.example.jp` であること、の2点を指定しています。

卒業・退職済み利用者宛のメールが破棄されるように、以下のように設定します。

```conf:/etc/postfix/expired_mailbox.cf
bind=yes
bind_dn=cn=mailsystem,ou=systems,dc=example,dc=jp
bind_pw=********
server_host=ldap.example.jp
server_port=389
timeout=20
search_base=ou=users,dc=example,dc=jp
scope=sub
query_filter=(&(uid=%u)(!(accountStatus=active)))
result_attribute=uid
result_format=discard
```

最後の `result_format` パラメータで、配送先を `discard` と指定していることがポイントです。`discard` は、Postfix の特殊な配送先の一種で、メールを全て破棄する配送先です。
デコレートしている関数の情報を取得する

運よく見つけたのでメモ。

```python:test.py
class hogehoge(object):

    def deco(func):
        def inner_deco(self):
            print(func.__name__)
            func(self)
        return inner_deco

    @deco    
    def func1(self):
        pass

    @deco
    def func2(self):
        pass

test = hogehoge()
test.func1()
test.func2()
```

出力結果

```
func1
func2
```

全く調べていないが、たぶんname以外にも様々な種類があり、
その関数の様々な情報をデコレータ側で取得できるのだと思う。
Google Mapの情報ウィンドウに複数の情報を表示するには

## はじめに
Google Map APIを使用してマップを表示できたので、情報ウィンドウを表示できるように実装をしています。
今回の実装では、その場所の名称と説明を改行して載せようとしました。
しかし、そこでつまづいたので解決方法を残します。

## やりたかったこと

以下のソースだと、nameだけが表示された状態なので、descriptionも表示させようとしました。

```rb

// nameは変数
infoWindow[i] = new google.maps.InfoWindow({
  content: name
});
```

## 失敗例①

変数を結合してみましたが、エラーになるようで地図が表示されなくなりました。

```rb

infoWindow[i] = new google.maps.InfoWindow({
  content: name + description
});
```

## 失敗例②

HTMLタグが使えるそうなので入れてみましたが、これもダメ。

```rb

infoWindow[i] = new google.maps.InfoWindow({
  content: name<br>description
});
```

## 成功した書き方

どうやら、HTMLタグを''で囲み、+で変数を結合する必要があったみたいです。

```rb

infoWindow[i] = new google.maps.InfoWindow({
  content: name   +
           '<br>' +
           description
});
```

## さいごに

このように、変数に予め代入しておくと分かりやすいですね。

```rb

var content =  name   +
               '<br>' +
               description;
```
UiPath Excelアクティビティでちょびっと裏技

2019/12/12現在、UiPath Studio のExcel系アクティビティには、新シート追加というアクティビティがない。

カスタムアクティビティを利用すればいいじゃん


…そうなんだけど。
自分のPCで作ったワークフローを客先にもっていって動かすときの不安。
できるだけ、Studioをインストールしたときにあるデフォルトのアクティビティで動かしたい！


というわけで、公式フォーラムにもあったちょっとした裏技をメモ。


#新シートを追加したい

アクティビティ「データ テーブルを構築」で空のデータテーブルを用意する。
データはスペースでも入れておくとよい。
出力の変数もわかりやすく。

![構築.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60895/f49b9f66-1d02-7f05-9fbc-8273cdfd380d.png)

データはスペースでも入れておくとよい。
出力の変数もわかりやすく。

アクティビティ「範囲に書き込み」で空のデータテーブルをExcelに書き込もうとする。

![新シート追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60895/93908309-a15f-089f-005e-4846713d98a8.png)

intCount.ToString("00") のところはお好きなシート名を付けてあげる。

実行すると好きなシート名でシートが追加される。

アクティビティ「ホットキーを押下(SendHotkey)」でもうまくいかないときは、こっちのほうが素直かも。

#シート選択したい

Excel窓の左上にある「名前ボックス」を使ってシート選択ができる。

![シート選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60895/22737800-8d55-081b-ee7d-962987679302.png)

「名前ボックス」をクリックして、文字入力「シート名!目的セル」にするだけ。
文字を入力した後にEnterを忘れると、シート選択されないので注意。

"01!A1[k(enter)]" は、シート名 01 の A1 を選択、という意味です。
Laravelリレーション初心者向け！外部キーがデフォルトでないパターン！！！


## foreign_key が `<テーブル名>_id` でない場合のリレーション

日本語ドキュメントはこちらです！
https://readouble.com/laravel/6.x/ja/eloquent-relationships.html

## やりたいこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308965/0925a54d-a33a-330b-8a27-d2f582b863da.png)

## まずは結論

```php:Status.php
class Status extends Model
{
    public function history()
    {
        return $this->belongsTo(History::class, 'post_number');
    }
}
```

```php:History.php
class History extends Model
{
    public function status()
    {
        return $this->hasOne(Status::class, 'post_number');
    }
}
```

```php:StatusController.php
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Status;

class StatusController extends Controller
{
    public function index()
    {
        $statuses = Status::orderBy('created_at', 'asc')->paginate(10);

        return view('status.index', compact('statuses'));
    }
}
```


```julia:index.blade.php
@foreach ($statuses as $status)
<tr>
　<td>{{ optional($status->history)->post_id }}</td>
</tr>
@endforeach
```

どっちが `belongsTo`? とわかりづらい場合は、
まっぴーさんのツイートを参考に！！！！！！！！！！！！！！！！！！！！！！！

https://twitter.com/mpyw/status/1197390766642847744

> 「常に第2引数が Foreign Key で，第3引数が Local Key です。基本的に Local Key はいじらない限りは "id" となるもので，何かしらテーブル名入ってる方は Foreign Key という覚え方でOK」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308965/e9916715-a3de-8c0f-f51f-315c6ef38b39.png)


とのことなので、 **第2引数が `id` などの Local Key になっていたら `belongsTo` と` hasOne` が逆** です。
あと公式ドキュメントにも

```php
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
```

と載ってるのですがここが大事なようです。
わたしはデータをとりにいくテーブル側が `hasOne` になる！と思い込んでたので最初は下記のようにしており、実際にデータも取得はできていたのですが、これだと、 Local Key が第2引数になってしまい正しい形ではないと！

```php:Status.php　❌
class Status extends Model
{
    public function history()
    {
        return $this->hasOne(History::class, 'id', 'post_number');
    }
}
```

ドキュメントに沿うと下記が正解なのではと思ったけど何故かデータ取得できず…。

```php:Status.php　❓
class Status extends Model
{
    public function history()
    {
        return $this->hasOne(History::class, 'post_number', 'id');
    }
}
```

そこで `belongsTo` と `hasOne` を反対にするとちゃんとデータも取得でき正しい書き方になったという結論です。（※まっぴーさんに教えてもらった）
ちなみにもし外部キーがデフォルトの、`<テーブル名>_id` であれば引き数は必要ないけれど、
（ `histories` テーブルに `status_id` があり、それを外部キーとしてデータを取得したい場合）
今回は違うので引数を割り当てます。

基本的には第３引数が `id` の形になると思われますが、

```php
return $this->belongsTo(History::class, 'post_number', 'id');
```

命名規則にのっていれば第３引数の `id` はデフォルトなので省略可能。

```php
return $this->belongsTo(History::class, 'post_number');
```

#### 無事データが取得できたか確認

```php
\DB::enableQueryLog();

Status::find(1)->history;

dd(\DB::getQueryLog());
```

取得結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308965/edce1bfc-9a87-bff2-b8a2-fe309502a884.png)
`bindings` の `0 => 1` の意味は、**「1つ目の `？` に `1` があてられる」**
当てはめると下記になる↓

```sql
select * from `statuses` where `statuses`.`id` = 1 limit 1;
select * from `histories` where `histories`.`id` = 18 and `histories`.`deleted_at` is null limit 1;
```

上記を heidiSQL や A5SQL などにコピペして求めてるレコードが取れているか確認します。
ローカルネットワークにWekanを構築した

## Wekanとは

所謂カンバンツールです。備忘録、タスク管理、プロジェクト管理などに使えます。
タスクをドラッグアンドドロップで移動できるので便利です。
英語でもKanbanなんですね。
![Wekan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202428/e194cff1-35d9-7838-e518-f67b7e42f1da.png)


## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/wekan) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

`docker-compose.yml`ファイルと、volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
xbyak_aarch64をGoogle Colabで動かす。

#はじめに
ARM用のJITコンパイラxbyak_aarch64を動かしてみる。ここでは、Google ColabでQEMUを使って動かす。なお、QEMUは、AARCH64の命令を(Google Colabのバイナリの前提である)x86_64の命令に変換するために使っている。

まず、以下のパッケージが必要である。

```
!apt update
!apt install binutils-aarch64-linux-gnu cpp-8-aarch64-linux-gnu cpp-aarch64-linux-gnu
!apt install g++-8-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-8-aarch64-linux-gnu gcc-8-aarch64-linux-gnu-base:amd64 gcc-aarch64-linux-gnu pkg-config-aarch64-linux-gnu
!apt install qemu qemu-block-extra:amd64 qemu-system-arm qemu-system-common qemu-user qemu-user-static qemu-utils qemu-system-aarch64
```
次に、環境変数を設定ののち、ソースコードのダウンロード、そしてサンプルコードのコンパイルおよび実行を行う。

- 環境変数設定
  - LD_PRELOADは、デフォルトだとtcmallocをロードするがうまく動かないので削除している。
- xbyak_aarch64のダウンロード
- コンパイル
- 実行　($3+4$の足し算をしている)

```
%env LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib
%env PATH=$PATH:/usr/aarch64-linux-gnu/lib:/usr/bin:/bin
%env LD_PRELOAD=
!ln -s /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/ld-linux-aarch64.so.1
!git clone http://github.com/fujitsu/xbyak_aarch64
!cd xbyak_aarch64/sample;aarch64-linux-gnu-g++ add.cpp
!/usr/bin/qemu-aarch64 xbyak_aarch64/sample/a.out
```

#注意事項
Qemu 3.1は、2018年12月にリリースされている。このため、Qemu 2.1が配布されているUbuntu 18.04では、すべての命令が動くとは限らない（コアダンプする場合がある）。よって、Qemu 3.1にマニュアルインストールするか、Ubuntu 19.04(Disco)以降に乗り換える必要がある。

#参考資料
- [Xbyak_aarch64 ; JIT assembler for AArch64 CPUs by C++](https://github.com/fujitsu/xbyak_aarch64)
- [qemu package in Ubuntu](https://launchpad.net/ubuntu/+source/qemu)
vSwitchにアップリンクが追加できないときの対象方法（ESX）

#概要
既存のvSwitch0に新たにアップリンクを追加しようとすると
下記のエラーが表示されてしまう。

**『この仮想スイッチに接続できる未使用の物理アダプタはありません』**

#原因
vSwitchに管理用vkernel（デフォルトだとManagementPort）がアタッチされている


#対処方法
ESXにログイン後
Configure Management Network
↓
Network Adapters
↓
アップリンクとして追加したいNICをスペースでチェックし、保存
Xcodeでファイル削除→テスト失敗した時の対処法

不要なファイルを削除した際は下記手順でビルド設定を変更する必要があります。

## 手順

1. ナビゲータでプロジェクトを選択し、Build Phasesタブを選択。
2. 検索窓に削除したファイル名を入力し、Compile Sources欄で削除したファイルを選択
3. 「ー」をクリックしCompile Sources欄から削除する。
link_to (Haml)タグにクラス名をつける


syntax error, unexpected keyword_ensure, expecting end-of-input

Haml in Rails：画像をリンクにするときのエラー：

間違えたコード：

```
= link_to %a{:href => "file:///Users/HOkaniwa/Desktop/IBplat%202/Questions%23index_home.html"}
　　= image_tag "logo2.png"
```
エラー：SyntaxError in QuestionsController#index

直したコード：

    %li= link_to image_tag('logo2.png', id:"logo"), questions_path
画像を使わない他の例：

    %li= link_to '質問する', questions_path, class: "a btn btn-default" 
直すこと
１：パス名を確認して直す。

（NameError in Questions#indexを直す） http://localhost:3000/rails/info/routes をみて、questions からquestions_path として正しいパスを書く。 この場合はindexアクションだったため、以下； = link_to 'image_tag "logo2.png"', questions_path

 
エラー：このままだとイメージタグが文字としてページに表示される。
ためしに' 'をなくしてみると = link_to image_tag "logo2.png", questions_path　となり、エラーが出る。
undefined method `symbolize_keys' for "/questions":String
 
2: image_tag('image名')　とする。

      = link_to image_tag('logo2.png'), questions_path
 
3: HTML inputを Haml text_fieldにする
エラー：Syntax error

```
=form_for :question, url: questions_path do |f|
%p
= f.label :質問タイトル
= f.text_field :question_title 'text_field',:class => "input form-control"
%p
= f.label :質問内容
= f.text_area :question_content
%p
= f.submit
-#もとのコード：
%input.form-control{:placeholder => "質問のタイトル", :type => "text"}
 
-#直したコード：
            = f.text_field :question_title, :class => "input form-control",:placeholder => "質問のタイトル", :type => "text"
【Python】requestsでwavファイルをPOSTする【POST】

#初めに
音声認識APIをHeroku上にアップしたのですが、
wavファイルをどうしたらpostして、受け取り側も取得できるのか、
文献が少なく試行錯誤したので、メモとしてのこしておきます。

###keyとかuserid, passなどはセキュリティ対策です。

#サーバー側
```python
from flask import Flask, request, abort
import soundfile as sf
from io import BytesIO
import os

app = Flask(__name__)

@app.route("/webapp", methods=['POST'])
def webapp():
    webaccesskey = request.headers["KEY"]
    webaccesspassword = request.headers["PWD"]
    if webaccesskey == "ok" and webaccesspassword == "foapkun":
        try:
            if request.args.get("TYPE") == "wav_message":
                user_id = request.args.get("USERID")
                key = request.args.get("KEY")
                valid = checker(user_id, key)
                if valid == True:
                    wavdata = request.files["file"].stream
                    audio_data, samplerate = sf.read(BytesIO(wavdata.read()))
                    #ここに入れたい処理
        except:
            abort(400)
    else:
        abort(400)
    return 'OK'

def checker(user_id, key):
    valid = False
    if user_id == "user_id":
        if key == "key":
            valid = True
    return valid


if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
```


#requests側
```python
import requests

class Message:
    def __init__(self):
        self.accessURL = "http://localhost:5000/webapp"
        self.accesskey = "ok"
        self.accessPASSWORD = "qiita"

    def put_wav(self, user_id, key):
        self.headers = {"KEY": self.accesskey, "PWD": self.accessPASSWORD}
        self.payload = {"TYPE": "wav_message", "USERID": user_id, "KEY": key}
        fileName = 'test.wav'
        files = {'file': open(fileName, 'rb')}
        r = requests.post(self.accessURL, headers=self.headers, params=self.payload, files=files)
        print(r.text)

if __name__ == "__main__":
    message = Message()
    message.put_wav(user_id="user_id", key="key")
```
GIFアニメの繰り返し再生回数を変更する

ImageMagickをインストール済みならば，手持ちのGIFアニメの繰り返し再生回数を簡単に変更可能です．

```terminal
$ convert -loop 回数 original.gif converted.gif
```

回数を0にすると無限再生になります．
（今更だが己は新鮮）AWS S3にファイルおくだけでWebサーバーか。WordPressから変換させて静的サイトなら格安？他のパターンは・・・

(2019/12/13 事後談追記) レンタルサーバー上にあったファイル数が少なかった(画像含め3MB以下)ので、S3への移行がブラウザのドラッグドロップですぐに完了。Webサイト開始の設定、読み取りセキュリティ設定、ドメインのCNAME設定をしました。無事に稼働を確認し、30分程度で一通り完了（S3バケット作るの初めてだったのですが）、レンタルWebサーバーの廃止ができてしまいました。ごめんなさいGMOさん！（従来はFTPでアップロード、バージョン管理もされていなかったので、Chromeブラウザだけでホイっと終わりバージョン管理もされる上にコストがレンタルサーバーと比較すると 500分の1？ 1000分1？と随分と削減になり便利になりました）
・　・　・　・　・
#サーバーレスってどこまで安価にできるのかな（今までWebサーバーでコスト削減発想がなかった）
AWSで簡易なWebサーバーを簡単に作る方法の「パターン資料」が見当たらなかったので整理してみました。ことの発端はAWS試験勉強でEC2など立てなくてもWebサーバーが立てられることが分かったからコスト削減になるかもしれないと思い立った（試験勉強って意味がないっていう人いるけど、何かのきっかけでそういえばこんなこと聞いたことがある！って思いつくことあるのですよね。そういう気付きを軽視する人って本当に残念だなあと思う）。現在はほとんどトラフィックがない（個人事業のような）簡単なホームページをGMOのレンタルサーバーにホスティングしているのですが、年間で1万円程度払っているはずなので、AWSでコスト削減もかねて何かできないか調べた結果です。

**（１）EC2 （IIS, Apacheなどのミドルウェアをインストール）**

サーバーレスではない一番オーソドックスなAWS上でのWebサーバー構築事例。~~オンプレでスキルが陳腐化したおっさん（私）が思いついていた~~ 唯一のAWS活用代表例、典型的なAWSパターン。結局のところ、国内レンタルサーバーから移植しようとしても高くつく理由で諦めるケースが多い。https://aws.amazon.com/jp/ec2/pricing/

**（２）S3のみで対応する**

S3はhttp表示が可能！
これで事足りてトラフィックもほとんどなければコスト削減になりそう。
静的なhtml，画像コンテンツのみに有効なパターン。
WordPressで作成されたサイトを変換してS3に放り込むこともできなくはない。
「工事中」などと簡易に表示させる場合やリダイレクトをしたい場合にも使えるテクニック。

動的なコメントページやメール転送などを考えると機能がなく完結しない。
内容の変更がほぼ発生しないことが前提の運用になる。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/WebsiteHosting.html
https://orizuru.io/blog/aws/s3-01/
https://qiita.com/dogwood008/items/a92abae789f4b0466f38

※WordPressの場合、WordPressがどこかに動く環境があり、
StaticPressプラグインを投入。S3転送用に構築したファイルをS3に流し込む作業が必要。
WordPress上で内容を変更した場合は再構築し再転送が必要。
　　WordPress/StaticPress関係の参考：
　　　https://dev.classmethod.jp/cloud/aws/staticpress-amazons3/
　　　https://14code.com/blog/20180509_1320/
　　　https://qiita.com/Ichiro_Tsuji/items/c6a52ec0ee95ead42f68
　　　http://webfood.info/staticpress-s3/
　　　http://ja.staticpress.net/
　　　https://github.com/megumiteam/staticpress-s3

**（３）S3 + CloudFront**

httpに加えてhttps SSLを実装しようとするとこちらが最低パッケージの様子。
重たいデータの配信、ワールドワイドの配信にも向いている。
小規模のサイトではまず使わなくて良いのではないか。
https://syobon.jp/blog/2018/04/16/how-to-build-static-site-using-wordpress/

**（４）Lambdaのみ**

これはありえない（はず）。
ブラウザ経由で中継なしに直接Lambdaを呼び出すことができない。

**（５）Lambda + API Gateway のみ**

S3だけでは不可能な https を呼び出しに使える。
１ページで完結する綺麗なデザインがない「工事中」のような単純なWebサイトや
リダイレクトをかけるだけのサイトならこの手も使えそう。
S3だけの場合と比較した際に場合によりこちらが候補になることもありそう。

https://canalier.com/aws-lambda-api-gateway%E3%81%AEhelloworld%E6%89%8B%E9%A0%86/
https://qiita.com/yoshidasts/items/d58c555aed2693e99ae6

**（６）Lambda+API Gatewayに加えてその他の組み合わせ ((+ Aurora, S3など))**

「Webサーバー」を立てなくてもいろいろできる。
https://www.cresco.co.jp/blog/entry/445/
https://qiita.com/hkusu/items/13af2b1a328719ea2946
https://engineers.weddingpark.co.jp/?p=1333
https://qiita.com/kimihiro_n/items/15cce90ec93625c4445a

**とりあえず今回は現行サイトに近い状態になるようファイルをS3に放り込み、レンタルサーバー解約の検討になりそうです。**
ローカルネットワークにGitLabを構築した

## GitLabとは

GitHubのOSS版のようなものです。
お仕事の都合でクラウドにソースコードを上げれないときに便利です。

## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/gitlab) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

`docker-compose.yml`ファイルと、volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
刻【とき】について語る時、いつも其処にはキミがいる

## 12月12日
### 08:30
動画配信サービスのネットワークトラフィックみたいな通勤電車の中で、つり革を掴む男性の右手首につけられた腕時計が目にとまった。シンプルだが上質そうなセイコー製のオートマチックアナログ。
規則正しく廻る長針と短針の下には、1から12までの数字が几帳面に並べられてた文字盤がある。
其処には、其れ以上も、其れ以下も存在しない。

### 09:45
出社と同時にタスクの確認をする。隙間なく埋められたスケジュールを眺め、短いため息をつく。
やれやれ、もしかすると彼らは1時間が60分だってことを忘れているのかもしれない。
通勤途中にコンビニで購入したカップ入りのコーヒーを口にふくむと、そこはかとなくロマンセ


### 12:00
昼食はいつも1人で済ませる。即席麺はお湯を入れて1分で食べる。
貴重な1時間の休息なのだ。1分だって無駄にはしたくない。

子供の頃、「どうして1分は60秒で１時間は60分なんだろう」と疑問に思った事はないだろうか。
そして、「どうして一日は24時間なのだろう」。。。と。

> 12 * 5 = 60
> 12 * 2 = 24

其処には、いつも12がいた。

### 19:00
定時が過ぎ、そそくさと会社を出ると外の寒さに一瞬だけひるんでしまう。もう12月なのだ。
年齢とともに1年という時間が加速しているように感じる。
これが、相対性理論か。

### 23:59
日付が変わる時間は何時だろう。私は多くの場合、その時間を24時と呼ぶ。
でも、その時間を0時と呼ぶ人もいれば、12時と呼ぶ人だっている。
どんな呼ばれ方をしようと、ソレは、ただ黙って日付を変えてしまうのだ。

## あとがき
まずはなによりも、 12さん に感謝もうしあげます。そして、協力してくれた 24くん と 60さん にも感謝を。

数字の世界って不思議ですよね。とても興味深いです。
今回、なぜ12になっているかについての詳細は **あえて** 記載しませんでした。
そういえば、なんでなんだろう？ というキッカケになれば幸いです。

あと、いつも途中で失速してしまうので来年は克服したいとおｍ
LattePanda Alpha 864s（OS非搭載モデル）に Windows 10 を新規インストール

# 概要
シングルボードコンピュータ「LattePanda Alpha 864s（OS非搭載モデル）」の開封からWindow10のインストール、ドライバの導入までの備忘録です。

# 初期状態

本体はスイッチサイエンスから購入。販売価格は、2019年12月12日の時点で47,080円です。別途、アダプタの購入も必要です。なお、ボードはむき出しなので静電気に要注意！（少なくとも付属のスタンドを取り付けましょう）

「OS非搭載モデル」ですが、初期状態で英語版の Window10 がプリインストールされています（ただし、ラインセンス認証がされていません）。

パッケージ同梱の「User Manual」の p.5 の「Getting started」の記載に従って操作すると、プリインストールされている Windows10 が立ち上がってきます。初回の起動は、かなり遅めです。また、<font color="red">ボード上の冷却ファンは温度が高くならないと回転しません</font>（寒い部屋で作業したので、最初のうちはファンが止まったままで初期不良か？と心配になりました）。

プリインストールの Windows が問題なく起動すれば、初期不良かどうかはチェックできますね。

今回は、この Windows ではなく、別途用意した Windows10 を LattePanda にインストールしていきます。

# インストールの準備

LattePanda は、USB接続のDVDドライブを接続し、そこからWindowをインストールすることはできないようです。一応、試してみたのですが、できませんでした。

そのため、ブート可能なUSBメモリを用意して、そこに Windows10 インストールディスクのイメージを展開して、それを使ってインストールしなければなりません。

## ディスクのイメージの取り込み

Windows10 のインストールディスクからイメージ（ISOファイル）を作成します。Windowの標準機能ではディスクからISOファイルを作成できないので、適当にソフトを探してきて使います。私は、StarBurn というソフトを使いました。

## USBメモリにISOファイルを書込み

ブート可能なUSBメモリとして設定しなければいけません。これも、Windowの標準機能でやろうとすると大変なのでソフトを使います。私は Rufus というソフトを使用しました（色々と細かい設定もできるようですが、デフォルト設定で書き込んで問題ありませんでした）。

USBメモリを用意して、Rufus を使って、先ほどディスクから取り込んだISOファイルを書き込みます。USBメモリの容量は、16GB のものを使用しました（8GBもあれば大丈夫なようです）。

# インストール

LattePanda の起動時（側面のパワーボタンを3秒押下したあと）に ESC を連打して UEFI/BIOS 画面に行きます。Boot のタブの `Boot Option Priorities` を次のように設定します。

```
Boot Option #1 [UEDI OS (Sony Storage Media 0100)]
Boot Option #2 [Disabled]
Boot Option #3 [Disabled]
```

つまり、起動優先順位の1番目に USBメモリ（今回はSonyのUSBメモリをつかったので上記のような表示になります） を割り当てて、あとは無効にしています。

私の場合、#2、#3 をしっかりと `[Disabled]` で無効にしないと（ #2 にプリインストールの Windows の `[Windows Boot Manager (MMC - HCG8a4)]` が割り当てられている状態だと）、USBメモリ からインストーラが起動しませんでした。

また、起動デバイスの候補に USBメモリが表示されなければ、インストール用USBメモリの作成に失敗していると思われます。

あとは、Save & Exit のタブから、`Save Changes and Reset` を選んで再起動してあげると、USBメモリからWindowsのインストーラが起動します。あとは通常のインストールと同じです。

なお、Windowsインストール後に、`Boot Option Priorities` は、もとに戻さなくても自動的に次のようになっていました。

```
Boot Option #1 [Windows Boot Manager (MMC - HCG8a4)]
Boot Option #2 [Disabled]
Boot Option #3 [Disabled]
```

# 各種ドライバのインストール

グラフィックスなどの基本的なドライバは Windows Update によって自動的にインストールされます（便利！）。ドライバを完全に最新にしたい場合は、[インテル ドライバー＆サポート・アシスタント](https://www.intel.co.jp/content/www/jp/ja/support/detect.html)にアクセスして、ドライバの確認とアップデートをかけます。

## つまずいたところ

上記インテルのサイトで最新ドライバをあてても、次のように **不明なデバイス** がひとつだけ残ってしまいます。とても気持ち悪いです。

![ドライバ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/3eeddb75-d4fa-b34a-82f5-887a41db7045.png)

デバイスのプロパティに「**Intel Serial IO I2C Host Controller - 9D61**」とあるので、それを探して手動で入れるだろうと思い、ネットで探してドライバの更新をやってみたのですが、失敗。

「なぜ？」と、結構な時間を使ってしまいました。

正解は、[LattePandaの公式HP](http://docs.lattepanda.com/content/alpha_edition/drivers_and_software/)にある Touch Panel Drivers をダウンロードして、手動で導入します。これで、デバイスマネージャー上では、すべてのデバイスが認識されました。

# おまけ

UEFI/BIOS 画面の Chipset タブから、冷却ファンの設定（何度以上で動き出して、何度以下で止めるか）が変更できます。
ローカルネットワークにCodiMDを構築した

## CodiMDとは

Markdownファイルを複数人で同時編集できるWEBアプリです。
プレビューが画面右に表示されるため、非常に便利です。
![CodiMD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202428/f079bf7b-46cd-2fe0-6029-fce28c45a0d9.png)

## 注意事項
ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/codimd) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

`docker-compose.yml`ファイルと、volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
Tie::Fileで大容量ファイルを処理する

この記事は[Perl Advent Calendar 2019](https://qiita.com/advent-calendar/2019/perl)の13日目の記事です。

12日目は@MacOlinさんの「Win32::OLEを使ったMicrosoft Wordの操作」でした。

**ちなみに、全然関係ないですけど今日って13日の金曜日なんですね！！**

## 結論（伝えたいこと）
Tie::Fileを使うと、ファイルの行に直接アクセスできる。
大容量ファイルへアクセスするときに便利。
さらに、読み込み時のキャッシュを多くすれば、ディスクI/Oを低減できてスピードアップする。

## きっかけ
プログラミング課題で、「省メモリで大容量のCSVファイルを短時間で処理するためのバッチプログラムを書いてほしい」というものがありました。

単純にメモリに格納するのでは効率が悪いと考えて色々試していたところ、Tie::Fileモジュールを使うとファイルの中身をすべてメモリに展開せず、ファイルに行指定でアクセスできることを知りました。

課題には、「外部のミドルウェア（RDBなど）に頼らず、プログラムで処理すること」と制約があったので、「それならこんな感じかなぁ。。」と思い、書いてみました。

モジュールの公式ドキュメントはこちらです。
https://perldoc.perl.org/Tie/File.html

## 前提
### 課題の内容
ざっくり言うと、以下の３条件を満たすプログラムを書くことです。

- サイズ1GB、レコード数700万の2つのCSVファイルに共通して存在するカラムから、文字列が完全一致する行を抜き出して単一の別ファイルに両方のファイルの行を出力せよ
- プログラムの使用メモリは1GB以内に収めよ
- それなりに遅くならないようにせよ（速度を意識せよ、みたいなニュアンスです）

要するに、「SQLで言うところのinner joinをやる」という意味です。

### 実行環境

- [OS] Windows 10 Home
- [CPU] Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2808 Mhz
- [Memory] 8GB
- [Perl] msys2上に構築

## Tie::Fileをどこで使うか
inner joinの内部表を作るときに使います。

まず、読み込みファイルをオープンします

```perl:fopen.pl
  my $obj2 = tie(my @array2, 'Tie::File', $file2, memory => 20_000_000)
    or die "File tie error : $!";
```

`memory`を明示的に指定すると、キャッシュをデフォルトの2MBから変更することができます。今回は、20MBに調整してファイルI/Oの削減を試みました。

`@array2`にはファイルの行情報が格納されているので、スカラで評価するとファイルの行数が取得できます。

適当な所で区切りながら、内部表を作ります。

```perl:create_inner_table.pl
    # 内部表作成
    my $inner_table = Match::InnerTable->new; # 内部表をハッシュ形式で作成するための自作モジュール

    # データは配列形式で格納されているため、ファイルの1行目は0になります。よって、$track_index2の初期値は0です
    # $row_size2は@array2をスカラで評価して-1します
    for my $i2 ($track_index2..$row_size2) { 

      my $line2 = $obj2->FETCH($i2); # 指定行を取り出す
      my ($id2, $email, $smtp, $datetime, $login_id2) = split /,/, $line2;

      .
      .
      .

      # データ挿入
      $inner_table->insert(key => $login_id2, value => $i2);
    }
```
指定した列をキー、キーが存在する行番号を値にしたハッシュを作成します。
これで、値に一行丸ごと挿入しなくて良くなるので省メモリになります。

実際のコードでは、比較したいカラムを予めソートしておいたり、一回で読み込むと1GBを超えてしまったので適当なところで区切りを入れたりしていますが、割愛してます。

あとは、もう片方のファイルを駆動表としてforループで処理し、キーにマッチした行を`FETCH`してゆけば良いです。実行環境では510secくらいで処理できました。メモリ使用量は700MBくらいでした。

## おわりに
なぜ全てメモリに展開せずに行を取り出すことができるのか、モジュールの実装を追って確かめてみたいと思います。

Perl Advent Calendar 2019, 明日の担当は, @mackee_wさんです.
アトリビュート(Rustの基本構文-9-)

#はじめに
Rustの基本的な文法についてまとめてみた。第9回。
今回のテーマは「__アトリビュート__」について.

###目的
Rustにおける基本的な構文の理解をする。

#Rustの基本構文シリーズ
第4回⇒[Rustの基本構文(4)](https://qiita.com/jin237/items/42249f984746711be0e2)　　URL： https://qiita.com/jin237/items/42249f984746711be0e2
第5回⇒[Rustの基本構文(5)](https://qiita.com/jin237/items/3fc3341effb3670e5865)　　URL：https://qiita.com/jin237/items/3fc3341effb3670e5865
第6回⇒[Rustの基本構文(6)](https://qiita.com/jin237/items/903e33226f93e7a4e5a0)　　URL：https://qiita.com/jin237/items/903e33226f93e7a4e5a0
第7回⇒[Rustの基本構文(7)](https://qiita.com/jin237/items/fcb5a05fb902dee1fc4d)　　URL：https://qiita.com/jin237/items/fcb5a05fb902dee1fc4d
第8回⇒[Rustの基本構文(8)](https://qiita.com/jin237/items/d544edcdfc7a08fa6998)　　URL：https://qiita.com/jin237/items/d544edcdfc7a08fa6998

#アトリビュート(attribute)
日本語にすると、「属性、特性」の意味を持つ。ただ、__Rust上では、アイテム宣言にメタデータを付けるためのもの。__
2つの書き方がある。
__・対象となるものより先に書く
・対象の中に書く__
この書き方によってそれぞれ形も変わってくる。

```
//対象となるものより先に書く
#[attribute]
//例(対象となるものより先に書く)
#[test]
fn test1(){
   本体
}

//対象の中に書く
#![attribute]
//例(対象の中に書く)
fn test2(){
   #![test]
   //本体
}
```
のようにして書く。__testアトリビュートは関数につけることのできるアトリビュートで、この関数はRustのコンパイラに--testというオプションを渡したときにだけ、コンパイルされる仕組み__になっている。

ここで様々アトリビュートに関することを説明していく。
##様々なアトリビュート
今回使用率の高いものを紹介していく。以下のもの。
・testアトリビュート（上記紹介より省略）
・cfgアトリビュート
・deriveアトリビュート
・allowアトリビュート
・denyアトリビュート

###cfgアトリビュート
__条件によって、コンパイルするかどうかを決めることができる。__

例を引用してくる。(from 実践Rust入門　言語仕様から開発手法まで P.245)

```rust
//ターゲットのOSがUnix系の場合にだけコンパイルする。
#[cfg(unix)]
fn something_for_unix(){
   //本体は省略
}

//ターゲットのOSがWindowsの場合にだけコンパイルする。
#[cfg(windows)]
fn something_for_windows(){
   //本体は省略
}
```
--testオプションのように、--cfgオプションでコンフィグレーションオプションをRustコンパイラに渡すこともできる。
###deriveアトリビュート
__deriveアトリビュートに対応したトレイトの実装を自動的に構造体や列挙型に実装__してもらえる。

```rust
//Point構造体にDebugトレイトが自動的に実装される
#[derive(Debug)]
struct Point{
    x: i32,
    y: i32,
    z: i32,
}

fn main(){
    let some_point = Point {x: 10, y: 20, z: 0};
    //Debugトレイトのfmt関数が自動的に実装されているので、:?フォーマット文字列をつかうことができる。
    println!("Debug: {:?}", some_point);
}
```
結果

```terminal
[Running] cd "c:\Users\[username]\rust\project1\" && rustc derive_attribute.rs && "c:\Users\[username]\rust\project1\"derive_attribute
Debug: Point { x: 10, y: 20, z: 0 }

[Done] exited with code=0 in _.___ seconds
```
これより正常に動いた。詳細については別記事にて説明。

###allowアトリビュートとdenyアトリビュート
リントチェックを制御するためのアトリビュートである。
・__allowで指定されたリントチェックは無視されるようになる。__
・__denyで指定されたリントチェックはエラーとして扱いを受ける。__

#さいごに
アトリビュートについては、わからない人も多いと思うが、これから使っていける機会があれば積極的に使えるようにソースコードに混ぜるなどしていきたい。
jQueryプラグインFlex Slider


## Flex Sliderは万能スライダー？

スライドショー用のjQueryプラグインってたくさんある〜。
[Skipper](http://austenpayan.github.io/skippr/)なども検討したのですが、どうやらFlex Slider はカスタマイズ性に非常に優れている様？？なので使ってみた :mouse: :hibiscus:

・ **レスポンシブ対応。**
・ **タッチコントロールのフリックスライドにも反応。**
・ **画像にリンクを貼ることもオッケー。**
・ **キャプションも表示可能。**
・ **動画もスライドできる。**
・ **コントロールボタンやナヴィゲーションも細かく設定できる**

など非常に使い勝手がよいプラグインの様です。

スライダープラグインをまとめている記事 :ledger:
[高機能なJavaScriptの人気スライダープラグイン4つを実際に使ってレビューしてみた](https://liginc.co.jp/web/js/jquery/158379)

## 導入手順

### 1. `FlexSlider`のプラグイン本体をダウンロード

[FlexSlider](http://flexslider.woothemes.com/)
![スクリーンショット 2019-07-05 9.43.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446210/f5be658f-e6b6-d26a-d7d2-ae1503ee925a.png)

### 2. `<head>〜</head>`内にダウンロードしたスクリプトとスタイルシートを読み込む。

ダウンロードした jquery.flexslider.js、flexslider.css のファイルを、jquery ファイルと一緒に設置。

```index.html
<link rel="stylesheet" href="flexslider.css" type="text/css" />
<script src="jquery.js"></script>
<script src="jquery.flexslider.js"></script>
```

### 3. htmlファイルのマークアップはこれだけ

```index.html
<div class="flexslider">
<ul class="slides">
<li><img src="slider1.jpg" /></li>
<li><img src="slider2.jpg" /></li>
<li><img src="slider3.jpg" /></li>
<li><img src="slider4.jpg" /></li>
</ul>
</div>
```

とてもシンプル。
次に最低限のjsの記述をしてこれで動く様になります。

```index.html
<script type="text/javascript" charset="utf-8">
$(window).load(function() {
$('.flexslider').flexslider();
});
</script>
```

## オプション

オプションの種類 :hugging: :fire:
[【jQuery】超万能スライダー FlexSlider の使い方をマスターする。](https://on-ze.com/archives/409)
シェルコマンドをコピペした時の "$: command not found" エラーをなくすために「$コマンド」を作った

[602 Advent Calendar 2019](https://adventar.org/calendars/4810) 12日目の記事です！

# 概要
シェルコマンドをコピペする時、頭に「\$」がついていても実行できるようにしました。

# 動機
Twitterにて、TLに現れた下記ツイートを見て思いつきました。（@nwtgckさん、きっかけをありがとうございます。そしてこれが初めてのQiita記事です！）
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">「\$ コマンド」を「コマンド」として実行してくれる「\$コマンド」どこかにないかな。コピペを実行しやすくなると思うんだよね。</p>&mdash; Ryo Ota (@nwtgck) <a href="https://twitter.com/nwtgck/status/1204732792963125249?ref_src=twsrc%5Etfw">December 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 
↓自分の返信
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">とても面白いですね！<br><br>#!/bin/sh<br>exec \$@<br><br>と書いた$ファイルをパスの通ったところ（例えば/binの中）に置いて実行権限をつければできると思います！</p>&mdash; りんわしゅう🤹‍♂️ (@Rinwasyu) <a href="https://twitter.com/Rinwasyu/status/1204738450496163840?ref_src=twsrc%5Etfw">December 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

# 背景 〜コピペコード〜
私はプログラミングの学習にWeb上の記事を活用しています。
その中で、サンプルコードが載っているサイトを使うと、コードをコピペして自分の環境で試すことができます。とても便利だと感じます。しかし、シェルコマンドのコピペをする際に困った問題があります。

```shell_session
$ hoge --option
$ fuga --option
```

このような「\$」が頭についていることがある点です。おそらく、シェルのプロンプトで実行している事を示すためにこんな表記をしているのだと思います。
ですが、コピペする時に「\$」までコピーして貼り付けてしまうと、実行時に

```shell_session
$: command not found
```

のようなエラーが出てしまいます。訂正をしなければならず、大変です。

# 解決方法
\$コマンドを作りました。
中身はシェルスクリプトで、

```shell
#!/bin/sh
exec $@
```

と書かれています。
1行目はShebangと言うものです。（無くても動くと思いますが）
2行目、execはシェルの組み込みコマンドで、シェルプログラム自身を別のコマンドやプログラムで置き換えることができます。置き換える対象は$@で、これはシェルの特殊変数の一つで、中にコマンドの引数すべての文字列が入っています。（この場合は実行したいコマンドの文字列）

このファイルを、/binや/usr/binなど、PATHの通ったディレクトリに保存し、

```shell_session
chmod a+x $
```

などで実行権限を付与したら完成です！

# 使ってみた
↓Before

```shell_session
user@mypc:~$ $ echo "Hello World"
$: command not found
user@mypc:~$ 
```

↓After

```shell_session
user@mypc:~$ $ echo "Hello World"
Hello World
user@mypc:~$ 
```

Hello Worldと表示できました。

# 感想
面白いアイディアを簡単に実装できて楽しかったです。すでに誰かが作っているものかもしれませんが、見たことが無いものを作る、ワクワクする体験ができました。ありがとうございました。@Rinwasyu宛にリクエスト送っていただけたら他にも面白いコマンド作るかもしれません・・・ｗ

# 余談
Bashなどでは、一般ユーザのプロンプトが「\$」でrootユーザのプロンプトが「\#」です。次はroot権限で実行できる\#コマンドを作ろう・・・！と思いましたが、\#はシェルスクリプトでコメントとして扱われるため無理でした。__残念__。
\#コマンドを実行するときは

```shell_session
user@mypc:~$ \#
```

とする必要があります。
リモートからNutanix(CVM)を操作。はじめてのPython

# やりたいこと
運用担当者さんと会話すると自動化(スクリプト化）が必須と言われることが多く、
運用の自動化の第一歩としてローカルPCからCVMを触ってみます。
改めて一から整理

# 準備
・Pythonのインストール
検索してインストール
・Paramikoのインストール
Pythonインストール後、コマンドプロンプトから下記を実行すると、paramikoがインストールできます（既に入ってるけど）
`pip install paramiko`

``` 
c:\cli>pip install paramiko
Requirement already satisfied: paramiko in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (2.7.1)
Requirement already satisfied: bcrypt>=3.1.3 in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from paramiko) (3.1.7)
Requirement already satisfied: pynacl>=1.0.1 in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from paramiko) (1.3.0)
Requirement already satisfied: cryptography>=2.5 in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from paramiko) (2.8)
Requirement already satisfied: cffi>=1.1 in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from bcrypt>=3.1.3->paramiko) (1.13.2)
Requirement already satisfied: six>=1.4.1 in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from bcrypt>=3.1.3->paramiko) (1.13.0)
Requirement already satisfied: pycparser in c:\users\tatsuhiromatsumoto\appdata\local\programs\python\python38\lib\site-packages (from cffi>=1.1->bcrypt>=3.1.3->paramiko) (2.19)
WARNING: You are using pip version 19.2.3, however version 19.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
``` 

# サンプルコード
cVMへログインし情報を取ってくる

##サンプルスクリプト
```
import json, paramiko

IP = '1.1.1.1'
USER = 'nutanix'
PASSWORD = 'pass-pass'

def main():
  output = get_df(IP, USER, PASSWORD)
  print(output)

def get_df(ip, user, password):
  client = paramiko.SSHClient()
  client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  client.connect(ip, username=user, password=password, timeout=3.0)
  command = '/usr/local/nutanix/bin/acli host.list'
  (stdin, stdout, stderr) = client.exec_command(command)
  output = stdout.read().decode()
  client.close()
  return output

if __name__ == '__main__':
  main()

```

##実行結果
```
c:\cli>python acli-list.py
Hypervisor address  Host UUID                             Schedulable  Hypervisor Type  Hypervisor Name
1.1.1.1        a99e2678-3f60-4b37-b201-5d0cfd226ed5  True         kKvm             AHV
1.1.1.2        1a1d1102-64ab-4cc1-a736-684a4ed83464  True         kKvm             AHV
1.1.1.3        de80adb3-f889-4139-bd68-b6e1d974d036  True         kKvm             AHV
1.1.1.4        a0dd6b68-25e5-48af-ab5f-e9ba62f67657  True         kKvm             AHV
```

# まとめ
Pythonを使ってCVMの情報を取ってみました。
サンプルコードのコマンド部分を変更すれば各種コマンドが実行できます。Hello Worldレベルです。
一度リモートから実行することでスクリプト化、自動化の敷居が下がると思います。
QGIS Pythonコンソールでパネルの表示/非表示を操作する

QGISのpythonプラグインからパネルの操作をしたい。
調べた。

参考にしたのは以下のやりとり。
https://gis.stackexchange.com/questions/317058/how-to-add-dockwidget-above-the-layer-panel-using-pyqgis

レイヤパネルをPythonコンソールで切り替えられたら
プラグインへの実装は簡単にできるよねー

というわけでPythonコンソールを起動して以下のコマンドを実行

```python 
# QGIS2系だとimportが必要
# from PyQt4.QtGui import QDockWidget

# レイヤパネルを取得（戻り値は配列）
layersPanel = [x for x in iface.mainWindow().findChildren(QDockWidget) if x.objectName() == 'Layers']

#表示するぜ
layersPanel[0].setVisible(True)

#消すぜ
layersPanel[0].setVisible(False)
```

できた。
objectNameに指定されている名前は上記のループでざーっと表示させてなんとなく探し当てるか
QGISのリポジトリで「[qgisapp.cpp](https://github.com/qgis/QGIS/blob/master/src/app/qgisapp.cpp)」から`  mLayerTreeDock->setObjectName( "Layers" );`みたいに追加しているところを探し当てるかになると思います。

以上
Aeのリピーターが使いたい

#理想とﾅﾝｶﾁｶﾞｳ

理想
<img width="266" alt="スクリーンショット 2019-12-12 15.33.14.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168611/2526af89-7ad3-6413-4e35-36e9883e8ecc.jpeg">

現実
<img width="302" alt="スクリーンショット 2019-12-12 15.23.21.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168611/0fc9234a-4834-bf5d-c7f2-8ac995be05ca.jpeg">

#「位置」を0,0にする必要があった

**位置がいっぱいある!**

- コンテンツ
     - 長方形
        - 長方形パス
        - 線
        - 塗り
        - トランスフォーム:長方形 **→ 位置 👈変えるべきはコレ!!!**
     - リピーター
         - トランスフォーム **→ 位置**
- トランスフォーム
    -  **位置**

１つのシェイプにこんなに沢山位置の値が設定できるなんて知らなかった…！



![3-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168611/4f05010b-0e98-e1f5-df4a-a6925d1f7fa9.gif)



▼参考記事
https://www.curioscene.com/ae-pop-effect-using-repeater/

▼ステキなリピーターの使い方(やってみたい
https://everydayskillshare.jp/2019/07/02/after-effects%E7%B0%A1%E5%8D%98%E3%81%AB%E3%83%AA%E3%83%94%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7/
超自己流まとめ　gem,bundler,gem install,bundle install,vendorについて

#この記事を書くことにした理由
英語の勉強方法は多少は板についてきたと思っているが、プログラミングの勉強方法は違うアプローチで行かないと全く用語も何もかも覚えられないと思ったので、試しに自分の言葉で読んだ記事をまとめて見ようと思ってます:v_tone1:

「この解釈は違うよ！」などありましたら、ご指摘お願いいたします:smile:

##gem
gemはRubygemsのコマンド 。


##bundler
bundlerは"Gemfile"と"Gemfile.lock"に従って、gemを管理をするライブラリ。
bundlerもgem.


## gem installとbundle installの違い

ruby言語のライブラリのことをgemという。
railsとかもgemになる。

`bundle install --path vendor/bundle`
↑これだ。

##vendor
`bundle install --path vendor/bundle`するとGemfileとGemfile.lockができる


##gemfileとgemfile.lock 役割
Bundler用の設定ファイル。
BundlerはGemfileの記述にしたがって、gemの依存関係を示したGemfile.lockを生成する。

##GemfileとGemfile.lock
GemfileとGemfile.lockは`bundle install --path vendor/bundle`この中に入る。


Gemfile.lockはGemfileをもとに実際にインストールされたgemの一覧とバージョンが記載されたファイルです。


言語力ぜろの私を許してください・・・:angel:

参考にしたサイト
https://qiita.com/nishina555/items/1b343d368c5ecec6aecf
https://qiita.com/tnoda_/items/a04e761d595a742fcdca
https://qiita.com/kamohicokamo/items/ded4cad5be1778547640
https://qiita.com/oshou/items/6283c2315dc7dd244aef
https://qiita.com/hisonl/items/162f70e612e8e96dba50
https://qiita.com/jnchito/items/99b1dbea1767a5095d85
http://xxxcaqui.hatenablog.com/entry/2013/02/11/013421
Swiftでカウントダウンタイマー作る。

## はじめに
アドベントカレンダー一個一個の質が低いのは許してください。
## 今回作るもの
下のような感じのタイマーです。
ただ単に400秒とか600秒とか10秒といった秒数からカウントを減らしていく記事は結構あったんですが下の画像のように、時間、分、秒まで対応した記事はぱっと見なかったので（多分ある）
記事書くことにしました。
今回ライブラリとか何も使っていないのですがそういうタイマーのライブラリとかあるんですかね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/a0b92634-9be9-eabe-7ddf-1bbadb7f3401.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/231db78a-2c8b-c963-bbed-bcd055ee7239.png)

## storyboard
**画像にも記載してありますがLabelを一つおくだけでいいです。
画像上にあるnavigationBarとか下の二つのラベルとか青い四角とか全部いらないです。**
分かりにくくてすみません。
#### まとめるとLabelを一つだけ配置しましょう
<img width="336" alt="スクリーンショット 2019-12-12 15.40.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/4f9aa3a5-0c42-ab3a-3199-2ee7b6a85b59.png">

## viewController
```swift:viewController
     //timerの時間(1時間,10分,10秒)
     var time: [Int] = [1,10,10]
    //さっき作ったlabelを紐づける
    @IBOutlet weak var timeLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        //labelの表示を初期化
        timeLabel.text = String(time[0]) + ":" + String(time[1]) + ":" + String(time[2])
        //1秒ごとに時間をtimerメソッドを呼び出す。
        Timer.scheduledTimer(timeInterval: 1, target: self, selector:#selector(timer) , userInfo: nil, repeats: true)
    }
    @objc func timer(){
        if (time[0] == 0 && time[1] == 0 && time[2] == 0) {
            timeLabel.text = "終了"
        } else {
            if time[2] > 0 {
                //秒数が0以上の時秒数を-1
                time[2] -= 1
            } else {
                //秒数が0の時
                time[2] += 59
                if time[1] > 0 {
                    //分が0以上の時、分を-1
                    time[1] -= 1
                } else {
                    //分が０の時、+59分、時間-1
                    time[1] += 59
                    time[0] -= 1
                }
            }
            timeLabel.text = String(time[0]) + ":" + String(time[1]) + ":" + String(time[2])
        }
    }
```

## 終わりに
解説はコメントに書いてある通りなんですがなんかネストしすぎてて見にくいので自分でするときはリファクタしてください。