OmniAICreator/Qiita-1.07M huggingface dataset:
Forkjoinについて -mergeとconcatを比較して-

# 前提として
ReactiveExtensionについて学ぶ必要があります。詳しくはこちらをご覧ください。

https://qiita.com/ryuseikurata/private/0970763ecd8fa7d75f15
https://qiita.com/ryuseikurata/private/d48945ed98a53d9e284c
https://qiita.com/ryuseikurata/private/6db14969b628e0de1d0c
https://qiita.com/ryuseikurata/private/fa5227a1203af86a19ab
https://qiita.com/ryuseikurata/private/45faa9cd8f50a390b10c

## emitとは
observableによって届けられたあとの受け取ったメッセージの処理の総称。

* next ・・・ Observableがメッセージを生成するたびにobservableによって呼び出される
* error ・・・　エラーが起きた時に呼び出される
* complete ・・・　完了した時に呼び出される


# Forkjoin
* observableが終了した時、引数のobservableからemitされたそれぞれを配列にしてemitする。


```typescript
//引数はobservableとなる。
const numberOne = of(1)

const array = numberOne.pipe(
          forkjoin(
                of(2),
                of(3)
               )
           );      
        
array.subscribe(val => console.log(val))
```

```typescript
[1,2,3]
```


# merge
* 引数のobservableを一つのobservableにまとめる。

```typescript
//observableを作る
const numberOne = of(1)
//number observableにof(2)とof(3)というobservableをmergeさせる
const array = number.pipe(
                  merge( 
                   of(2), 
                   of(3)
                  )
                );

array.subscribe(val => console.log(val));
```

```typescript
1
2
3
```

# concat
* 複数のobservableを順にemitしていく。（一つのobservableにするわけではない

```typescript

//observableを作る
const numberOne = of(1)
// of(1), of(2), of(3)の順にemitされる
const array = number.pipe(
                 concat( 
                     of(2), 
                     of(3)
                  )
                 );
array.subscribe(val => console.log(val));
```

```typescript
1
2
3
```
管理画面のURLにBasic認証を設定する方法(EC-CUBE3系/4系)

EC-CUBE3系/4系で、管理画面にBasic認証をかけるTipsです。

先日、EC-CUBE3.0.17/4.0.1がリリースされました。
その中で、.htaccessにBasic認証のサンプルが記載されるようになっています。

https://github.com/EC-CUBE/ec-cube/blob/4.0/.htaccess#L58

使い方は簡単で、

- `.htpasswd`を作成する
- `.htaccess`のサンプルのコメントアウトを外す(パスを調整する必要があります)

で利用できます。

## .htpasswdを作成する

ここではhtpasswdコマンドを使って`.htpasswd`を作成する手順を紹介します。

```
$ cd [ec-cubeのルートディレクトリ]
$ htpasswd -b -c .htpasswd [ユーザ名] [パスワード]
```

`.htpasswd`が作成できていたら成功です。

## .htaccessのコメントアウトを外す

`.htaccess`のサンプルの記述を以下のようにコメントアウトを外します。

```
# 管理画面へのBasic認証サンプル

AuthType Basic
AuthName "Please enter username and password"
AuthUserFile /path/to/.htpasswd
AuthGroupFile /dev/null
require valid-user

SetEnvIf Request_URI "^/admin" admin_path  # ^/adminは, 管理画面URLに応じて変更してください
<RequireAll>
    Require all granted
    Require not env admin_path
</RequireAll>
```

`AuthUserFile /path/to/.htpasswd`の行はec-cubeの設置パスに変更します。
例えば、`/var/www/html/ec-cube`にEC-CUBEを設置した場合は、

```
AuthUserFile /var/www/html/ec-cube/.htpasswd
```
となります。

`SetEnvIf Request_URI "^/admin" admin_path`の行は、管理画面のURLに応じて変更します。
管理画面のURLが`kanri`であれば、

```
SetEnvIf Request_URI "^/kanri" admin_path
```

となります。

以上で設定は完了です。

管理画面にアクセスし、Basic認証のダイアログがでれば成功です。
もしエラーになる場合は、パスに誤りがないか確認してみてください。
CakePHP 第12会MeetUpに参加しました！

先日、[CakePHPの3.7系がリリース準備中、あれ、4系は？第12回CakePHP MeetUp](https://cakephp.connpass.com/event/110405/)
に参加しました。
簡単にどういう事をしたのか簡単に書きたいと思います。

##概要


>CakePHPを使っている、これからCakePHPを学ぶ人たち向けの、交流と勉強を目的としたミートアップイベントです。日常抱えている疑問を聞いたり、実際に使った感想や他のフレームワークとの違いなど、お互いに色々話し合いましょう。

冒頭で記載したページの引用になります。

ここで記載されているように、目的としては交流と勉強。
今回のMeetUpは、自分の感覚値として、交流8、勉強2という感じでした。

##内容

###1. 自己紹介

まず簡単に自己紹介をしました。
参加者全て異なる企業の方でした。

###2. 交流

今回のMeetUpの参加者は7人で、自分ともう一人の方が初参加という感じで、他の方は何回か参加されているという感じで、終始和やかな雰囲気でした。

話した内容としては、
- MeetUpの概要説明
- 以前のMeetUpの様子
- 来年開催されるCakeFestについて
- 日々の開発業務でのCakeに関するお話し

ざっくりいうとこんな感じです。

###3. マイグレーションガイドを読む

今回のお題が`「CakePHP の3.7系のマイグレーションガイドを読もう」`で、3.6系が最後で次は4系が出ますよ、っていうアナウンスがあったものの、3.7.0-RC2がリリースされているという事だったので、そのガイドを読んでどんな変更や追加部分などがあるのか、というのを把握するというものです。

正直ここで自分はついていくのに必死でした笑

経験が浅い、は言い訳にしたくないのであれですが、もっと今使ってるCakePHPというフレームワークに対する知見を深めなくては、と本当に思いましたね。

一つのフレームワークの知見を深める事は、次新しいフレームワークを勉強した際に大いにその知見は役に立つと思いますし、新しい技術に目がいきがちで自分が使ってる技術の知見が浅いと結局ミーハー止まりで、いわゆる`ダサいエンジニア`になり兼ねないので。笑


##感想

今回はMeetUpという事で冒頭にも書きましたが、交流8：勉強2で、`学び`というより`気づき`の方が多かった印象です。

気づきの中には[CakeFest](https://cakefest.org/)というイベントの存在を知る事ができたという事です。

日本で開催されるかはともかく、そういうイベントがある事自体知らなかったですし、一切聞いた事がありませんでした。

参加者中には海外で開催された時のCakeFestに参加された方もいて、その方からのCakeFestに関するお話が非常に興味深かったので、ぜひ参加したいなと思ってます。

こういう話って話している方からすると当たり前のような感覚だと思うんですが、全く知らない自分のような人からすれば、相当大きな情報というか、MeetUpの良さを感じられた瞬間でもあるので、行ってよかったと思っています。

CakeFestの話に少し戻すと、来年開催されるCakeFestも多くの海外の方が参加される見込みらしいので、英語はマストというか、参加したからには海外のエンジニアとお話したいですし、そのお話しするチャンスが日本に来るんですから生かさない手はないかと！

今後のキャリアを考えた時に海外での挑戦は選択肢にありますし、というかむしろ行きたいですし、2019年は英語も平行して勉強する年になりそうです。
なりそうというか今年の8月くらいからそういうプランで生活しているんですけどね笑

英語の話でいうと[楽天テックカンファレンス 2018](https://tech.rakuten.co.jp/)に参加した時に、楽天という企業柄当たり前なのかもしれませんが、終始英語でした。

とてももどかしい気持ちになったので、個人的に来年の英語学習はマストなわけです。
で、たまたまその英語を生かせそうな場がめちゃくちゃあるので、2019年非常に楽しみなのです！

少し脱線しましたが、このMeetUpで感じた事は、
`外部のエンジニアの方ともっと密に交流した方が良いという事`
`今使っている技術の知見を深める必要性`
の二つです。

今後も積極的にMeetUpや勉強会など、外部のイベントに参加して都度アウトプットしていこうと思います！


##お知らせ

このMeetUpを通してCakePHP公式のSlackに参加しました！
参考：[CakePHP公式の日本語話者向けSlackチャンネル開設のご案内](https://qiita.com/chinpei215/items/3c116171c5308365c314)

`japanese`というチャンネル名が、主に日本の方がいるチャンネルになります。

結構活発に動いているので、情報収集などにも生かせます。

入っていない方はぜひ上記記事を参考に参加してみてください！

##おまけ
Twitterやってます！外部のエンジニアの方ともどんどん繋がりたいと考えていますので、是非フォローして頂ければと思います！[@Tatsuo96](https://twitter.com/Tatsuo96)
p.s.今年の2月までは溶接職人でした。ガッツ系エンジニアとしてやらせて頂いております。
【rails5】当月、前月、翌月の値を取得する方法

###【rails5】当月、前月、翌月の値を取得する方法

月初と月末の日付を取得したかったので調べました。

コンソールで

```
 Date.current
 => Mon, 10 Dec 2018 
```
で今日の日付が取得出来ます。

***Date.current***の後に、

```
今月　Date.current.month
前月　Date.current.prev_month
次月　Date.current.next_month
月初　Date.current.beginning_of_month
月末　Date.current.end_of_month
```
と付けることでそれぞれの値を取得できる。

```
now = Date.current
```

繋げて

```
前月の月初
now.prev_month.beginning_of_month
=> Thu, 01 Nov 2018 00:00:00 JST +09:00
```


前月の月初の日にちが取得できました。


今回は月だけを表示させたいので、***strftime***でフォーマットを変更します。

```
前月の月初
now.prev_month.beginning_of_month.strftime("%m")
=> "11"
```

出来ました。

年も同じです。

```
今年
 Date.current.year
 => 2018 
```

ちなみに過去や未来を取得するには、

```
n年前
Date.current.ago(n.years)

n年後
Date.current.since(n.years)
```

で取得できます。

```
3年後
> Date.current.since(3.years)
 => Fri, 10 Dec 2021 00:00:00 JST +09:00
``` 

もし１年と7か月前などにする場合は***month***を使って、

```
１年と7か月前
Date.current.ago(19.month)
 => Wed, 10 May 2017 00:00:00 JST +09:00 
```

で出来ました。

ちなみにTime.currentだと時間まで取得出来ます。

```
Time.current
 => Mon, 10 Dec 2018 08:29:13 JST +09:00 
```
JSONについて調べてみた


#JSONとは
JavaScript Object Notation
データを表現するための記法です。
JavaScriptの構文に似ていますが、JavaScriptとは独立して扱われます。
JavaScript以外のプログラミング言語でもJSONを扱うことができる機能が準備されています。


#形式
JSONは`オブジェクト`、もしくは`配列`で表現されます。

###オブジェクト

```lang:JSON
{
 "key" : value,
 "key" : value,
 "key" : value
}
```

`オブジェクト`の中に、`key`と`value`のペアである`メンバー`を複数含むことができます。
このメンバーは順序付けされていません。

- メンバー(`"key" : value`)は`,`で区切って複数定義することができる
- `key`は`"(ダブルクォート)`で囲む必要がある(シングルクォートではだめ)
- 一つの値を分断しない限り、改行やスペースを自由にいれることができる(そのため上記のように成形することができます)
- `value`は以下の型を取ることができる

| 型 | 説明 |
|:--|:--|
| 文字列 | "(ダブルクォート)で囲む必要がある |
| 数値 | 10進数、指数表記を使うことが可能(8進数、16進数は使うことができない) |
| オブジェクト |   |
| 配列 |   |
| boolean | true/false。小文字の必要がある |
| null | 小文字の必要がある |


サンプル

```json
{
  "user" : {
    "name": "Taro",
    "age": 30,
    "languages": ["Japanese", "English"],
    "active": true
  }
}
```

###配列
以下のように、配列として扱うこともできます。

```json
[
  {
    "name": "Taro",
    "age": 30,
    "languages": ["Japanese", "English"],
    "active": true
  },
  {
    "name": "Aiko",
    "age": 33,
    "languages": ["Japanese"],
    "active": false
  },
  {
    "name": "Hanako",
    "age": 29,
    "languages": ["English", "French"],
    "active": true
  }
]
```
   
#JavaScriptでのJSONの扱い方

###環境
* Windows10
* Node.js 10.14.1

###Jsonデータの作り方

```js
var userJson = {
  "name": "Taro",
  "age": 30,
  "active": true
}
console.log(userJson.name);
// Taro
```

###オブジェクトをJSON文字列に変換する

```js
var userObj = {
  name: "Taro",
  age: 30,
  active: true
}
console.log(userObj);
// { name: 'Taro', age: 30, active: true }

var userJson = JSON.stringify(userObj);
console.log(userJson);
// {"name":"Taro","age":30,"active":true}
```

`JSON.stringify`を使用することで、オブジェクトデータをJSON文字列へ変換することができます。

###JSON文字列をオブジェクトに変換する

```js
var userObj = {
  name: "Taro",
  age: 30,
  active: true
}
var userJson = JSON.stringify(userObj); // JSON文字列へ変換
console.log(userJson);
// {"name":"Taro","age":30,"active":true}
console.log(userJson.name);
// undefined

var parsed = JSON.parse(userJson); // オブジェクトへ変換
console.log(parsed);
// { name: 'Taro', age: 30, active: true }
console.log(parsed.name);
// Taro
```

`JSON.parse`を使用することで、JSON文字列をオブジェクトへ変換することができます。
JSON文字列の状態では、プロパティにアクセスすることはできませんが、オブジェクトへ変換することでプロパティにもアクセスすることができるようになります。
Serverlessでランタイム環境が別の関数をデプロイできるようにする

ちょっとしたサービスとかで、Node.jsとGoを利用するのに、serverless.ymlを分けたくなかったので調べてみました。


## ランタイムは関数ごとに指定できる

Serverkessの公式ブログにありました。

How to use multiple runtimes in a single serverless microservice
https://serverless.com/blog/building-mutliple-runtimes/

```runtime``` だけでなく、```package``` も関数ごとに指定できました。

Serverless Framework Guide - AWS Lambda Guide - Packaging
https://serverless.com/framework/docs/providers/aws/guide/packaging#packaging-functions-separately

```yaml:serverless.yml_関数ごとにruntimeを指定する例
service: hoge

provider:
  name: aws

functions:
  nuxt-renderer:
    runtime: nodejs8.10
    handler: handler.render
    memorySize: 512
    timeout: 30
    package:
      exclude:
        - ./**
      include:
        - .nuxt
        - node_modules
        - static
        - "*.js"

  api:
    handler: api/bin/main
    package:
      exclude:
        - ./**
      include:
        - api/bin/**
```

便利です^^


## 参考

How to use multiple runtimes in a single serverless microservice
https://serverless.com/blog/building-mutliple-runtimes/


Serverless Framework Guide - AWS Lambda Guide - Packaging
https://serverless.com/framework/docs/providers/aws/guide/packaging#packaging-functions-separately
[Vue]devServerでフロント開発中、別ポートで起動しているバックサーバーにリクエストを送る方法

# やりたいこと

- vue-cli3でプロジェクトを作成
- yarn serve でフロント開発サーバーを8080で起動
- axiosか何かを使って、9081でローカル起動しているバックエンドアプリにリクエストを飛ばす
- つまり、フロントとバックの開発が同時にできる

# やり方

- プロジェクト直下に vue.config.js を作成
- 以下を記述

```ts
module.exports = {
    devServer: {
        proxy: {
            "/api": {
                target: "http://localhost:9081",
            },
        },
    },
}
```

これで、フロントから
localhost:8080/api/some
を飛ばすと
localhost:9081/api/some
に変換される。

変換というよりはdevServerを経由して9081に送られているので、ブラウザの開発者ツールで確認しても8080にリクエストを投げたことになっている。
QMLで使うモデルをC++で実装する

# はじめに
Qt勉強会＠Tokyo 会場係のAtsushi4です。こんにちは。

[Qt Advent Calendar 2018](https://qiita.com/advent-calendar/2018/qt)の10日目の記事は、cppのモデル(QAbstractItemModelのサブクラス)とQMLの連携に関するお話です。

QMLのListViewでUIを作る時、皆さんはmodelをどう作りますか。
JavaScriptのArrayを使う、QMLのListModelを使う、.qmlファイルでモデルを定義する、などの方法もありますが、私はcppのモデルクラスとして実装するのが割と好きです。

ここでは、私が普段モデルクラスを実装する時に、なんとなく気を付けている事を書きます。

# 気をつけていること

## アイテムクラス
データ1レコードを表すクラスです。なるべくPOD型のように使えて、signal/slotのQueuedConnectionができて、デバッグ出力ができて、QMLでも使えるクラスを目指します。

* SharedDataなクラスにする。
* Q_GADGET, Q_PROPERTYを使い、メンバー変数をプロパティとして実装する。
* メンバー関数をQ_INVOKABLE宣言する。
* swap関数を実装し、Q_DECLARE_SHAREDする。
* Q_DECLARE_METATYPEする。
* qRegisterMetaTypeする。
* QDebugへの出力オペレータを実装する。

### コード例

~~~cpp:addressitem.h
#ifndef ADDRESSITEM_H
#define ADDRESSITEM_H

#include "cppmodel_global.h"
#include <QtCore/QSharedDataPointer>
#include <QtCore/QObject>
#include <QtCore/QDate>
#include <QtCore/QMetaType>

class AddressItemData;

class CPPMODELSHARED_EXPORT AddressItem
{
    Q_GADGET
    Q_PROPERTY(QString name READ name CONSTANT)
    Q_PROPERTY(QString kana READ kana CONSTANT)
    Q_PROPERTY(QString email READ email CONSTANT)
    Q_PROPERTY(QDate birthday READ birthday CONSTANT)
public:
    AddressItem();
    AddressItem(const QString &name,
                const QString &kana,
                const QString &email,
                const QDate &birthday);
    AddressItem(const AddressItem &);
    AddressItem &operator=(const AddressItem &);
    ~AddressItem();
    inline void swap(AddressItem &other) {return data.swap(other.data);}
    bool operator==(const AddressItem &other) const;
    inline bool operator!=(const AddressItem &other) const {return !(*this == other);}
    const QString &name() const;
    const QString &kana() const;
    const QString &email() const;
    const QDate &birthday() const;

private:
    QSharedDataPointer<AddressItemData> data;
};

Q_DECLARE_SHARED(AddressItem)
Q_DECLARE_METATYPE(AddressItem)

#ifndef QT_NO_DEBUG_STREAM
class QDebug;
CPPMODELSHARED_EXPORT QDebug operator<<(QDebug debug, const AddressItem &item);
#endif // QT_NO_DEBUG_STREAM

#endif // ADDRESSITEM_H
~~~

~~~cpp:addressitem.cpp(抜粋)
namespace {
int metaTypeId = qRegisterMetaType<AddressItem>();
}
~~~

## モデルクラス
ListViewのmodelプロパティに指定するクラスです。QMLプラグインのプロジェクトを作り、qmlRegisterTypeでQML側に公開します。
非同期にデータを読み込み、おおもとのデータを変更することなくソートやフィルタリングができるクラスを目指します。

* QSortFilterProxyModelクラスのサブクラスにする。
* アイテムクラスのリストを持つQAbstractListModelのサブクラスを作り、setSourceModelする。
* roleNamesを実装する。
* dynamicSortFilterをtrueにする。
* アイテムを追加するappendRow(s)関数をQ_INVOKABLE付きで宣言し、実装する。
* アイテムクラスを返すget関数を実装する。
* 64ビット整数型を使用する代わりにQStringを使用する。
* データを読み込むクラスは別のQML Typeとして実装する。

※コード例は省略

# おわりに
QML側でモデルを準備するととても簡単に書けるので、私もプロトタイプなどQMLにモデルをべた書きすることが良くあります。それに比べてcpp側でモデルを実装するのはかなり面倒な作業です。
でもQWidgetベースでもQMLでも使えて、うまく作ればListViewで取り回しやすく、QML側の実装がとても楽になります。あとはもう少し簡単にリストモデルが作れると良いんですけどね。

明日は@shin1_okadaさんです。お楽しみに！
【VR学まとめ】1.1 バーチャルリアリティとは何か

# はじめに

この記事は[一人VR技術者認定試験 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/vr-engineer)の2日目の記事です。

[バーチャルリアリティ学](https://www.amazon.co.jp/バーチャルリアリティ学-舘-暲/dp/4904490053)の1章「バーチャルリアリティとは」の内容をまとめていきます。
書籍の方も是非ご購入いただいた上でご利用ください。

# 1 バーチャルリアリティとは

## 1.1 バーチャルリアリティとは何か

### 1.1.1 バーチャルの意味

バーチャルの意味や訳を正しく理解しようというセクションである。

**Virtual = 「表層的にはそうではないが、本質的にはそうである」**

バーチャルは「本質的な」という形容詞なので、反意語としてはノミナル「名目上の」となる。
よく訳される「仮想」は「仮に想定した」という意味で、本質的であるという意味は持たないので誤用である。
また「虚」と訳されることもあるが、これは「実体のない」という意味であるので誤りである。
整理すると、VirtualはRealと類義語であることが分かる。

次のように訳されることも (太線は引用者によるもの)

> Existing in **essence or effect** though not in actual **fact or form**

![JPEG image-2D1B23DBC0E5-1.jpeg](https://qiita-image-store.s3.amazonaws.com/0/55365/da5c88ff-2a53-4c53-4608-37259ad97df4.jpeg)

**正しい意味のバーチャルの例**

- バーチャルマネー
    - クレジットカードや電子決済を意味する言葉
    - みかけはお金でないがお金としての効果を発揮する
- バーチャルカンパニー
    - 従来の会社の体裁はなしていないが、従来の会社と同じ機能を有している = 本質的な会社

### 1.1.2 バーチャルリアリティとその三要素

バーチャルリアリティは「現実のエッセンス」
_エッセンス = 本質的なもの_

本質は目的によって変わる。

例: バーチャルヘリコプターの意味の解釈

- 操縦士のトレーニングが目的の場合
    - フライトシミュレーター
- 輸送が目的の場合
    - 気球

**バーチャルリアリティの三要素**

-  3次元の空間性
    -  人間にとって自然な3次元空間を構成している
-  実時間の相互作用性
    -  人間がその中で環境と実時間の相互作用をしながら自由に行動できる
-  自己投射性
    -  その環境と使用している人間とかシームレスに鳴っていて環境に入り込んだ状態が作られている

### 1.1.3 バーチャルリアリティと人間の認知機構

バーチャルリアリティが、そこにないのに、そこにあると感じさせる仕組み。
人間が現実をどうやって認識しているかを知る必要がある。

人間は、物自体を認識しているのではなく、人間の認知機構によって認識している。
←人間の認識する世界も、人間の感覚器による一種のバーチャルな世界であると言える。

「認識の本質部分を与えれば等価な認識を与えることができる」という主張。

### 1.1.4 バーチャルリアリティの概念と日本語訳

日本には本来バーチャルという概念が存在しなかったため、「仮想」というニュアンスが定着してしまった。
バーチャルリアリティの適切な訳は存在しないが、強いて言えば「**人工現実感**」と訳すのが良い。

また、無理に訳そうとせず、バーチャルはバーチャルという言葉で使うのが良い。

### 1.1.5 道具としてのバーチャルリアリティ

VRは
3C (`Creation:創造`,`Control:制御`,`Communication:通信`)
と
3E (`Elucidation:解明`,`Education:教育`,`Entertainment:娯楽`)
のための道具

# まとめ

バーチャルという言葉のニュアンスを正しくとらえることが、非常に重要だと感じました。

[一人VR技術者認定試験 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/vr-engineer)の3日目は[【VR学まとめ】1.2 VRの要素と構成](https://qiita.com/nkjzm/items/0435c0093e1a62285be1)です。
NodeREDでみんな大好きIGRの時刻表をスクレイピング


岩手県立大学アドベントカレンダーなので岩手っぽいネタにします。

最近NodeRED（enebular）をよく使うので勉強がてらスクレイピングにチャレンジします。

@omega999くんの[みんな大好きIGRの時刻表をスクレイピング](https://qiita.com/omega999/items/fa3748523a8f6d7178d1)の記事インスパイアです。

## IGR

みんな大好き、[いわて銀河鉄道](http://www.igr.jp/)ですね。

![](http://www.igr.jp/wp/wp-content/themes/igr/images/logo.gif)

今回は滝沢駅の時刻表を抜き出してみます。 http://www.igr.jp/wp/timetable/takizawa

<img src="https://i.gyazo.com/2bc58213e88462ac960571b8899dc59b.png" width="400">

最終的にこんなJSONとして出力してAPI化します。

<img src="https://i.gyazo.com/d66599cc085f67b49fb0dff39c0af00b.png" width="300">

## enebularでスクレイピングチャレンジ

### まずはそのままHTMLリソース取得

https://enebular.com

* http in
* http request
* http response
* debug

の各ノードをつなげます。

![](https://i.gyazo.com/83318b4dc44ab658b99f046ed0899f1b.png)

`http requestノード`のURLに今回のエンドポイントになる滝沢駅の時刻表ページ`http://www.igr.jp/wp/timetable/takizawa`を指定します。

デプロイしてURLにアクセスしてデバッグコンソールを確認します。

![](https://i.gyazo.com/4c907eaeaaf99d01b03ed0bf5212cad2.jpg)

ちゃんと取れてますね。

これをカスタマイズしてみましょう。

### htmlノードを利用

他にいいやり方があるかもしれないですが、 **htmlノードを使うとHTMLからCSSセレクタを使用して要素を取り出すことが出来る模様。**
便利そう。

![スクリーンショット 2018-12-10 4.07.23.png](https://qiita-image-store.s3.amazonaws.com/0/35387/9ae0854c-42c3-bc35-5802-60f4112d91b1.png "スクリーンショット 2018-12-10 4.07.23.png")

ということで使ってみます。

調べたところ`class="post"`の中のp要素に時刻表が入っている模様です。

> ![スクリーンショット 2018-12-10 4.09.54.png](https://qiita-image-store.s3.amazonaws.com/0/35387/bece2b4b-68e2-97a1-f0cd-9054100a0c53.png "スクリーンショット 2018-12-10 4.09.54.png")

こんな感じに設定してあげるとそれっぽい時刻表が取得できました。

* 抽出する要素: `.post p`
* 出力: 要素のテキストのみ, 要素毎の複数のメッセージ

![](https://i.gyazo.com/e0eec8fdfe52d280e4c64e1f5e71bf35.png)

p要素が配列で取得できているイメージです。

### Switchノードで絞り込み

**県大生がよく使うであろう滝沢駅から盛岡駅方面への電車（上り）を絞り込みます。**

Switchノードで`盛岡`という言葉が含まれている要素を絞り込みます。

* contains: `盛岡`

![](https://i.gyazo.com/628996493440e7bd40723053f953a9d7.png)

### functionノードでjsonに整形

最後にfunctionノードを挟んでJavaScriptを記述します。最後はhttp outのノードにつないであげればJSON出力されます。

![](https://i.gyazo.com/2fa9a723c05a40a50dc18c2f5c96124e.png)


```javascript
const tmp = msg.payload.match(/(.*) (.*)/g); // ６：１６ 盛岡の形式を取得

let content = [];
for(let i = 0,len = tmp.length; i<len; i++){
    const item = tmp[i].split(' ');
    content.push({
        time: item[0],
        destination: item[1]
    })
}

msg.payload = {
    title: '滝沢駅上り',
    items: content
}
return msg;
```

`msg.payload.match(/(.*) (.*)/g);`の箇所で正規表現でマッチした時刻情報を配列として取ってきて、for文の箇所でjsonに整形しています。

### 結果

使い勝手がいいかわからないけどJSON出力できました。

<img src="https://i.gyazo.com/d66599cc085f67b49fb0dff39c0af00b.png" width="500">

## まとめ

functionノードを使わずに既存のノードを駆使したいところでしたが、NodeRED力がなさすぎて限界を感じました苦笑

もっとスマートにやれる方法が思いつく人がいたらぜひ教えてください！
HugoをLAN上のiPhoneからプレビューする方法

## 手順
### Step1. IPアドレス確認
まずはMacのIPアドレスを確認する．
`ifconfig`でeth0を見るか，設定アプリ＞ネットワークから確認する．

### Step2. Hugo server 起動
仮にIPが`192.168.0.20`だったとして，

```
$ hugo server --bind 192.168.0.20 --baseURL=http://192.168.0.20
```

でHugoを起動する．
コマンドオプションは後の補足説明参照．

### Step3. （初回時のみ）ネットワークアクセスを許可
初回起動時だと次の画像のように許可を求められるのでHugoに権限を与える。許可は後で取り消すことが可能。

<img width="418" alt="macOS.png" src="https://qiita-image-store.s3.amazonaws.com/0/285675/a20e0906-4e5b-b5f7-8059-101ef8002c2d.png">

### Step4. 任意の端末からアクセス
その後iPhone（に限らず他のコンピュータ）から，
`192.168.0.20:1313`にアクセスすれば完了！

## 補足説明
コマンドオプションについて．

| オプション         | 説明              |
|:-----------------|:------------------|
| `--bind`         | デフォルトでは`127.0.0.1`．この値をMacのIPまたは`0.0.0.0`に変更することで他のLAN上のコンピュータからアクセス可能になる． |
| `--baseURL`      | ホスト名・パスの設定．CSS反映がうまくいかない場合はこのオプションを追加すると良い． |

### よりシンプルな方法
仮にMacの名前がMyMBPだとしたら，mymbp.localでLANからアクセスすることもできる（Macの名前は設定アプリ＞共有から確認できる）．その場合は`hugo server --bind 0.0.0.0`で起動し，他端末から`mymbp.local:1313`にアクセスすれば良い．


---
参考：
https://discourse.gohugo.io/t/site-preview-from-smart-phone-in-lan-is-not-possible/2951/2
[メモ] らずぱいにJupyterLab (Docker使用)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75594/9742cc15-3c9d-8046-6bf0-72ee09887fa1.png)


# 概要
- Raspberry Pi 3で、JupyterLab
- Dockerイメージ作成
- [GitHub - kleinee/jns : jupyter notebook and lab on Raspberry Pi](https://github.com/kleinee/jns)<br>こちらのスクリプトを参考・使用して、`Dockerfile`を作成
- \# OpenCVとかインストールされてません.. 

<!--
# TL;DR

```bash
docker run -d --rm -v `pwd`:/home/pi/notebooks -p 8888:8888 mt08/rpi-jns-base
```

ブラウザにて、`http://raspberrypi.local:8888`(または`http://<ラズパイのIP>:8888/`)にアクセス。
パスワードは、`jns`

-->

# 環境
- Raspberry Pi 3B+ 
- `2018-11-13-raspbian-stretch-lite.img`
- microSD 16GB



# 手順
1. Raspbianの準備

	1. `2018-11-13-raspbian-stretch-lite.img`をEtcherなどで焼く
	2. パッケージ更新・初期設定・必要なパッケージ導入など

		```bash
		# パッケージ更新
		sudo sh -c 'apt update && apt upgrade -y'
		#
		# 必要なパーッケージ.
		sudo apt-get install -y git
		#
		# おこのみで.
		sudo apt-get install  htop byobu
		#
		# 初期設定: hostname、WiFi, タイムゾーン、言語など.
		sudo raspi-config

		#
		# 一度リブート
		sudo reboot
		```
2. Docker導入

	```bash
	# Dockerのインストール.
	curl -sSL https://get.docker.com/ | sh && sudo usermod -aG docker ${USER} 
	#
	# 再起動
	sudo reboot
	```


3. Dockerイメージ作成(時間がかかる)

	```bash
	# gitクローン。 `docker`というブランチ。
	git clone -b docker https://github.com/mt08xx/jns.git
	cd jns
	#
	#ベースイメージのダウンロード
	docker pull resin/rpi-raspbian:stretch
	#
	# イメージ作成: TAG名は、お好みで。
	TAG_NAME=rpi-jns-base
	docker build . --rm -t ${TAG_NAME}
	```





4. 実行

	```bash
	TAG_NAME=rpi-jns-base
	# 作業フォルダ
	mkdir ~/notebooks && cd ~/notebooks
	docker run -d --rm -p 8888:8888 -v `pwd`:/home/pi/notebooks ${TAG_NAME}
	```

	ブラウザにて、`http://raspberrypi.local:8888`(または`http://<ラズパイのIP>:8888/`)にアクセス。
	パスワードは、`jns`


# TODO

- コンテナの自動起動設定の説明
- jupyterの設定変更と保存
- `docker-compose`で、もうちょっとラクに(?)する
- オプショナルなものの導入方法(TeX, Pi hardware, Julia, SQLite, OpenCV) 
- DockerHubへ、push.. 

# その他
1. ビルド時間とサイズなど

	```shell-session:(参考)ビルド時間とサイズ
	pi@raspberrypi:~/jns $ time docker pull resin/rpi-raspbian:stretch

	real    0m48.604s
	user    0m0.520s
	sys     0m0.081s
	pi@raspberrypi:~/jns $ time docker build . -f Dockerfile --rm -t ${TAG_NAME} 2>&1 | tee ../build1.log
	...
	...

	real    39m56.512s
	user    0m1.206s
	sys     0m0.651s
	pi@raspberrypi:~/jns $ docker images
	REPOSITORY           TAG                 IMAGE ID            CREATED              SIZE
	rpi-jns-base         latest              1fa41f1b5e1f        About a minute ago   2.9GB
	resin/rpi-raspbian   stretch             21dc8fc1377f        6 weeks ago          139MB
	pi@raspberrypi:~/jns $ 
	pi@raspberrypi:~/jns $ df -h
	Filesystem      Size  Used Avail Use% Mounted on
	/dev/root        15G  4.3G  9.7G  31% /
	devtmpfs        460M     0  460M   0% /dev
	tmpfs           464M   80K  464M   1% /dev/shm
	tmpfs           464M   12M  452M   3% /run
	tmpfs           5.0M  4.0K  5.0M   1% /run/lock
	tmpfs           464M     0  464M   0% /sys/fs/cgroup
	/dev/mmcblk0p1   44M   23M   22M  51% /boot
	tmpfs            93M     0   93M   0% /run/user/1000
	pi@raspberrypi:~/jns $ 
	```
abc 115　D 再帰

C

```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int INF = 1e9;
int main() {
	int N, K;
	cin >> N >> K;
	vector<int>V;
	int h;
	for (int i = 0; i < N; ++i) {
		cin >> h;
		V.push_back(h);
	}
	sort(V.begin(), V.end());
	int M = INF;
	for (int i = 0; i < N - K + 1; ++i) {
		M = min(M,V[i + K-1] - V[i]);
	}
	cout << M << endl;
	return 0;
}
```
114と比べてかなり易しくなったと思う

D
とある世界では、今日はクリスマスです。
高羽氏のパーティで、彼は多次元バーガーを作ることにしました。レベル Lバーガー (Lは 0以上の整数) とは次のようなものです。
レベル 0バーガーとは、パティ 
1枚である。
レベルLバーガー (L≥1)
とは、バン 1枚、レベルL−1バーガー、パティ 1枚、レベルL−1バーガー、バン 1枚、をこの順に下から積み重ねたものである。
例えば、パティを P、バンを B で表すと、レベル 
1バーガーは BPPPB (を 90度回転したもの)、レベル 2バーガーは BBPPPBPBPPPBB といった見た目になります。
高羽氏が作るのはレベルNバーガーです。ダックスフンドのルンルンは、このバーガーの下から X層を食べます (パティまたはバン 1枚を 1
層とします)。ルンルンはパティを何枚食べるでしょうか？

```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
#include<stdio.h>
#include<cstdio>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int INF = 1e9;
ll mod = 1e9 + 7;
ll Len[55], Pat[55];//バーガーの厚さとパティの総数
ll rec(ll level, ll layer) {
	if (level == 0)return 1;
	if (layer == 1)return 0;
	else if (layer <= Len[level - 1] + 1) {
		return rec(level - 1, layer - 1);
	}
	else if (layer <= Len[level - 1] + 2) {
		return Pat[level - 1] + 1;
	}
	else if (layer <= 2 * Len[level - 1] + 2) {
		return Pat[level - 1] + 1 + rec(level - 1, layer - Len[level - 1] - 2);
	}
	else {
		return 2 * Pat[level - 1] + 1;
	}
}
//レベルNバーガーの下からX層に含まれるパティの総数をrec(N,X)とする
signed main() {
	ll N, X;
	cin >> N >> X;
	Len[0] = Pat[0] = 1;
	for (int i = 1; i <= N; ++i) {
		Len[i] = Len[i - 1] * 2 + 3;
		Pat[i] = Pat[i - 1] * 2 + 1;
	}
	cout << rec(N, X) << endl;
	return 0;
}
```
初のd問題。再帰。
蠟引紙（ろうびきし）でアドベントツリー作ってみた

# ＜ 序章 ＞

先日、妻に急に「ろう引きするよっ」って言われて
「なにそれ？」って警戒心まる出しなリアクションをとりましたが、
まあやってみたら
思のほかいい感じになったので、ご紹介です。

みなさんも

## さあ、ろう引きするよっ

材料：　ろうそく、紙、クッキングシート
道具：　アイロン、アイロン台、ポリ袋、ハンマー（叩けるもの）、
あれば良いかも：　不要な布（紙より大きな）、木枠

材料は100均で買えます。紙は私はA4用紙使いました。

ろうそくの量は私の場合、A4用紙１枚で１本。
３号サイズ？を一本ですかね？
１１２ｇ／１０本入りをキャンドゥで買いました。
とにかく、数枚作る程度だと１箱とかで十分かと思います。

## ついでにアドベントツリー作ろうよ

ただの紙をろうびきするのではつまらないので、
アドベントツリーを作ってみたいと思います。
アドベントツリーは我が家の造語で
アドベントカレンダーをクリスマスツリー的なデザインでやることを意味します。

そして、ここまでで何のプログラム的な技術的な要素がありませんので、
無理矢理アプリにしようかと思います。（やっていくなかで思いついたら）

# ＜ １章 デザインを決める ＞

ここは適当でOKです。
アドベントツリーはやはりモミの木が良いと思います。実にそれっぽいです。
クリスマスツリーとしてあまり飾られる前の写真なりイラストが良いかと思います。

![tree_v1.1_web.jpg](https://qiita-image-store.s3.amazonaws.com/0/324734/b2104fca-ef0b-d60f-df7a-7781e1ecd1db.jpeg)

ノリで2018としましたが、あとで思ったこととして、
つけなければ来年以降も使えたなと思いました。。

# ＜ ２章 下準備 ＞

ろうそくを粉々にします。
ポリ袋などにろうそくを入れて、ハンマーなどで叩くと良いです。

そこまで頑張ってに粉にする必要はないですが、
後でアイロンする際に粒が大きすぎるとやりにくいです。（でもいつかは溶けます）
試しながら徐々に粉々にしてもいいでしょう。

# ＜ ３章 ろうびきする　＞

アイロン台に用紙をクッキングシートで挟むようにしておきます。
パン　＞　肉　＞　パン　の容量で、
クッキングシート　＞　紙　＞　クッキングシート　です。

この後、アイロンで伸ばすのですが、クッキングシートから蝋がはみ出すかもしれませんので
クッキングシートを大き目にとるか
さらに下にいらない布などを敷くと良いかと思います。

次に、紙（肉）の上にろうそくソースをかけて、アイロンでなじませます。
蝋の量が多いと、ただただハミ出していくのみですので、加減しながらどうぞ。

まんべんなく沁みたら完成です。
詳しくは「ろうびき　紙」でご検索ください。

# ＜ ４章 完成　＞

こうなりました。（なんかすでにシール貼られてますが、、、）

![tree_web.jpg](https://qiita-image-store.s3.amazonaws.com/0/324734/996841f7-df78-846e-1ad4-9ca65aee84f4.jpeg)

ちょっとわかりにくいので、
フレームにはめた版も載せておきます。

![tree_result_web.jpg](https://qiita-image-store.s3.amazonaws.com/0/324734/bb174bc4-eddb-9c98-5174-75ebcedea183.jpeg)

![tree_result2_web.jpg](https://qiita-image-store.s3.amazonaws.com/0/324734/0330b21e-cffc-9a7d-22a1-54736a1ca1db.jpeg)

ありがとうございました。

そのうち、このコンテンツをもとに
デジタルアドベントツリーつくろうと思います。
Go言語でTwitterAPIを使ってツイート検索

APIのお勉強のためにTwitterAPIを使ってツイート検索をしてみた。
まずは、Standard searchからやってみる。

##用意するもの
Consumer API keys
Access token
Access token secret

こちらを参照してください:https://ahiru8usagi.hatenablog.com/entry/TwitterAPI_KeyAndToken

##ソースコード
まずはOAuth認証

```go:main.go
	config := oauth1.NewConfig(consumerKey,  consumerSecret)
	token := oauth1.NewToken(token, tokenSecret)
	httpClient := config.Client(oauth1.NoContext, token)
```

これでAPIの機能を使うことができる。
早速ツイート検索の関数を書く。

```go:main.go
//JSONオブジェクトについてはAPIリファレンスを参照してください
func search_tweet(client *http.Client)([]Tweet, error){

	values := url.Values{}//クエリの作成
	values.Add("q", "#golang")//検索ワード(これだけ必須)

    //リクエストの送信
	request, err := http.NewRequest("GET","https://api.twitter.com/1.1/search/tweets.json"+"?"+values.Encode(), nil)
	if err != nil {
		return  nil, err
	}

    //レスポンスの取得
	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var result Result//検索結果のJSONオブジェクト
	json.Unmarshal(b, &result)
	response.Body.Close()

	return result.Statuses, nil//Tweetオブジェクトを返す
}

```

これでTweetオブジェクトが返ってくる。

コード全体

```go:main.go
func search_tweet(client *http.Client)([]Tweet, error){

	values := url.Values{}
	values.Add("q", "#golang")


	request, err := http.NewRequest("GET","https://api.twitter.com/1.1/search/tweets.json"+"?"+values.Encode(), nil)
	if err != nil {
		return  nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var result Search_response
	json.Unmarshal(b, &result)
	response.Body.Close()

	return result.Statuses, nil
}

func main(){
	config := oauth1.NewConfig(consumerKey,  consumerSecret)
	token := oauth1.NewToken(token, tokenSecret)
	httpClient := config.Client(oauth1.NoContext, token)

	result, err := search_tweet(httpClient)
	if err != nil{
		fmt.Println(err)
	}

	for _, tweet := range result{//デフォルトでは15個のTweetを拾ってくる
		fmt.Println("text:"+tweet.Text)//テキストの表示
	}
}

```

実行すると15個のツイートが表示される。

Standard searchでできることは限られていて、検索可能なツイートが1週間以内の物だけだったりする。(多分)無制限にツイートの検索ができるPremium search APIの無料バージョンがあるのでそっちのほうで現在開発(？)中。

今回TwitterAPIで使うJSONオブジェクトの説明を飛ばしましたが、下記のリンクにTwitterAPIのリファレンスが載っているのでそちらを参照してください。
https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html
Javascriptで質問があります

プログラミング初心者です。現在ユーザーが入力したテスト成績をもとに、GPAを算出するプログラムを書いています。ユーザーが入力したデータを保存するコードを作成しているのですが、エラーが解決できません。どなたか教えて頂けますと幸いです！

HTML

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <link type="text/css" rel="stylesheet" href="index.css">
    <title>GPA計算表</title>
  </head>

  <body>
    <div class="top">
      <h2>Subject</h2>
      <input type="text" class="add__description" placeholder="Subject">
     </div>
     <div class="top middle">
       <h3>Exam1</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
       <h3>Exam2</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
       <h3>Exam3</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
       <h3>Final</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
       <h3>Participation</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
       <h3>Assignment</h3>
       <input type="text" class="add__percentage" placeholder="Percentage"><p>%</p>
     </div>

     <input type="button" value="submit" class="add__btn">
     <script src="system.js"></script>
  </body>
</html>


Javascript

var calcController = (function() {

  var data = {
    settings: {
      exam1: 0,
      exam2: 0,
      exam3: 0,
      final: 0
    },
    participation: 0,
    assignment: 0
  };


return {
  insertData: function(obj) {
    return {
   data.settings.exam1 = obj.exam1.value;
   data.settings.exam2 = obj.exam2.value;
   data.settings.exam3 = obj.exam3.value;
   data.settings.final = obj.final.value;
   data.participation = obj.participation.value;
   data.assignment = obj.assignment.value;
 };
 },

 publictest: function() {
   console.log(data);
 }
};


})();

var UIController = (function() {

  var DOMstrings = {
    Description: '.add__description',
    Percentage: '.add__percentage',
    btn: '.add__btn'
  };

  return {
    getGrade: function() {
      return {
        subject: parseInt(document.querySelector(DOMstrings.Description).value),
        exam1: parseInt(document.querySelector(DOMstrings.Percentage).value),
        exam2: document.querySelector(DOMstrings.Percentage).value,
        exam3: document.querySelector(DOMstrings.Percentage).value,
        final: document.querySelector(DOMstrings.Percentage).value,
        participation: document.querySelector(DOMstrings.Percentage).value,
        assignment: document.querySelector(DOMstrings.Percentage).value
      };
    },

    getDOM: function() {
      return DOMstrings;
    }

  };

})();

var controller = (function(UICtrl, calCtrl) {
  var input, DOM;

  DOM = UICtrl.getDOM();
   input = UICtrl.getGrade();

  calCtrl.insertData(input);

  document.querySelector(DOM.btn).addEventListener('click', insertData);
  document.addEventListener('keypress', function(event) {
    if(event.keyCode === 13 && event.which === 13) {
      insertData();
    }
  });




})(UIController, calcController);
Firebaseを駆使して数独を解くWebアプリを作ってみた　前編

#概要
こんにちは。Aidemyの刀根です。
Firebaseを駆使して数独を解くwebアプリを作成します。

ソースコードの全容はGithubの方で見てください。この記事に載せちゃうと記事の長さがえげつないことになるので。。。
[Githubはこちら](https://github.com/Swordroot/Sudoku)

また、今回作成したwebアプリは[こちら](https://sudoku-fa55e.firebaseapp.com/)で公開しています。

#システムの概要
firebase hostingで最低限のフロントエンドを作り、firebase cloud functionで数独を解くバックエンドを作成します。

#回答アルゴリズムを実装する前に・・・
まずはフロント側を実装していきます。今回はjQuery使ってゴリゴリ実装していきます。
そして今回は作ったものをfirebase hostingでホスティングします。
今回はデバッグのために各ますに入る数字の候補を確認できるようにもしました。
[index.html](https://github.com/Swordroot/Sudoku/blob/master/public/index.html)
[index.css](https://github.com/Swordroot/Sudoku/blob/master/public/css/index.css)
[send.js](https://github.com/Swordroot/Sudoku/blob/master/public/script/send.js)


#アルゴリズム
実装方針としては
1. 人が解くのと同じ方法である程度空きマスを埋める
2. バックトラックで残りを埋める

の２段階で実装していきます。

#人が解く方法を実装していく
今回は[こちら](http://www.sudokugame.org/solv/)のサイトに掲載されている解法からいくつか抜粋して実装していきます。

##ルールによる候補削除
まずは数独のルールに則り候補を削除していきます。

この処理の流れは以下の通りです。
1. 左上から順番に走査していく
2. 数字が入っているマスに当たったら、その行・列・ブロックに該当するマスの候補からその数字を消す
3. 右下までチェックし終わったら、確定できるマスがないかチェックしていく
4. もし新たに確定したマスがあったら、また1.に戻り繰り返す

[byRuleHelper.ts](https://github.com/Swordroot/Sudoku/blob/master/functions/src/helpers/byRuleHelper.ts)

#今回はここまで
だいぶ長くなってしまうので今回はここで一旦区切ります。次の記事でこの続きを書くのでそれまでしばらくお待ちください。（12月13日公開予定）

ちなみにまだバックトラックを実装していませんが簡単な問題ならこれだけでも解くことが可能です。
Unity2018.xで開発するにあたって知っておきたいNativeContainerの概要

# 最初に

この記事はUnity2018.x系の目玉機能を使用するにあたって知っておきたいNativeContainerについての概要を簡単にまとめたものとなります。

## NativeContainerって？

C#が提供している安全なContainerとは異なり、**アンマネージドなメモリ**を提供しつつもListやDictionaryのように扱えるContainerのことです。つまりGCでは管理されないので**自分でDisposeを行う**必要があります。そのため、幾つか守るべきルールとリスクを伴いますが、**高速に動作**しますし、C# JobSystemにおいてNativeContainerを使用することで**メインスレッドとの共有データにアクセス**できます(C# JobSystemについては次回の記事で概要を記載します)。

NativeContainerの持つ特徴は以下の4つです。

- Allocator（メモリの割当タイプ）を自身で決める(後述)。
- 使用後はDisposeで開放する必要あり。でないとメモリリークを起こして警告が出る。
- 使えるのは構造体のみ
- 要素数を増やせない

NativeContainer自体はunsafeなC#で書かれているため、新たに自身で[NativeContainer]属性を付加したコンテナを定義することも可能です。ただし通常の**NativeContainerは競合が発生した場合は例外発生とログ出力が行われて検出可能**ですが、自作コンテナの実装がうまくいっていない場合は(当然ですが)クラッシュする可能性があります。

## NativeContainerの種類

|配列名|概要|
|:----|:----|
|NativeArray\<Value>|通常の配列。|
|NativeSlice\<Value>|NativeArrayから一部切り取るのに使用。|
|NativeList\<Value>|追加と削除が容易。List。|
|NativeHashMap\<Key, Value>|キーと値のペア。Dictionary。|
|NativeMultiHashMap\<Key, Value>|キー毎に複数の値を持つ。複数Dictionary。|
|NativeQueue\<Value>|先入れ先出し(FIFO)の待ち行列。|

## Allocatorのタイプ

Allocatorの種類を設定するタイミングとしては、NativeContainerを実際に作成する時です。

```C#
// 引数としては、(要素数, Allocatorの種類)
var a = new NativeArray<MyStruct>(30, Allocator.Persistent);
```
種類の説明は以下の表の通りです。下に行くほど重くなります。

|種類|説明|
|:----|----|
|Allocator.Temp|メモリの割当と開放が最も高速。1フレーム以下での使用を目的としており、スレッドセーフではない。Tempを指定してメモリを確保した場合は関数呼び出しから戻る前にDisposeメソッドを呼び出して開放する。つまりそのフレームのみ有効。|
|Allocator.TempJob|メモリの割当と開放はTempより遅くなる。4フレーム以内での使用を目的としており、スレッドセーフである。4フレーム以内にDispose等で開放を行わないと警告を出力する。ジョブ終了時に自動開放させるオプションが有る。殆どの小規模なJobが、この種類を使用する。|
|Allocator.Persistent|メモリの割当と開放が最も遅いが、アプリの存続期間中、永続的な割当を行う。mallocのラッパー。TempJobを用いるよりも長いJobの場合に使用することがある。使用後はDispose等で開放。パフォーマンスが重要な場所では使用が推奨されない。|

## ReadOnly/WriteOnly属性

NativeContainerフィールドにはReadOnly(読み取り専用)タグ又はWriteOnly(書き込み専用)タグという属性を定義できます。ReadOnlyタグを付与することで**複数のJobが並列にデータへアクセスすることが可能**になります。

```C#
[ReadOnly]
public NativeArray<Vector3> position;
```

デフォルト(属性なし)の状態だとNativeContainerは読み書きが可能です。そのため**メインスレッドから結果を取り出すこと**が可能です。

# 最後に
今後の記事でECSとJobSystemについての概要を紹介するつもりですが、その取っ掛かりとして知っておきたいNativeContainerを調べてまとめてみました。私自身は初めてみる機能だったため、調べてみることでJobSystemに入る前の準備ができたような気がします。次はいよいよJobSystemについてざっくり見てみたいと思います。


# 参考
- [【Unity】C# Job Systemを自分なりに解説してみる](http://tsubakit1.hateblo.jp/entry/2018/03/04/223804)
- [NativeContainer](https://scrapbox.io/pf35301/NativeContainer)
- [NativeContainer(Unity公式)](https://docs.unity3d.com/Manual/JobSystemNativeContainer.html)
- [【CEDEC2017】C#JobSystem を使った Unity流マルチスレッドプログラミング](https://www.slideshare.net/UnityTechnologiesJapan/cedec2017cjobsystem-unity?ref=http://tsubakit1.hateblo.jp/entry/2018/03/04/223804)
- [ECSとJobSystem 基礎](http://esprog.hatenablog.com/entry/2018/05/19/150313)
Object detection実装：最低限のtraining pipeline実装

前回まではimage augmentationなど前処理に関する関数を実装してきた。

今回の[コミット](https://github.com/festa78/objdet-tf/commit/c41e630e2b1fc20ae187061b3e6f24c7a6fab8e8)では、
全体を繋げてYOLOV2の学習が開始できる最低限のパイプラインを実装する。

具体的に実装したのは以下：
1.データ、モデル、損失関数、最適化関数などを入力として学習を開始するクラスTrainer
2.データ、モデル、損失関数、最適化関数を具体的に定義してTrainerクラスにフィードする学習スクリプト
3.Yamlベースのメタパラメータファイル

Trainer内では、損失関数から得られる損失の平均だけをとりあえずモニターするようにした。
学習スクリプトでは、YOLOV2をVOC2007データセットに対して学習するようにした。

次のステップとして、mAPなどの別指標の実装、またtensorboardに表示するためのvisualizationも実装する。
Yoctoで作ったLinuxのパッケージをアップデートする(dnf)

[Aptpod Advent Calendar](https://qiita.com/advent-calendar/2018/aptpod) 10日目の担当、矢部です。

Aptpod入社してまだ日が浅い私ですがいろいろと新しく知ることが多く、その中に[Yocto](https://www.yoctoproject.org/)があります。
今回はYoctoで作成したLinuxパッケージをアップデートするための方法の一つである、パッケージマネージャの利用について説明します。

# 手順

Yoctoでパッケージマネージャを使う方法は非常に簡単です。設定ファイルであるlocal.confに以下を追加するだけ[^1]です。

[^1]: 1行目はlocal.confよりも、イメージ用のレシピファイルに追加するほうが自然かもしれません

```conf:local.conf
IMAGE_FEATURES += " package-management "
PACKAGE_CLASSES ?= " package_rpm "
```

2行目のほうはパッケージにrpmを利用する場合で、ほかにも

- package_deb
- package_ipk
- package_tar

が設定可能です。
設定ができたらイメージのビルド。

# パッケージリポジトリの公開

作成したパッケージはローカルにrpmファイルをおいてアップデートする方法もありますが、リポジトリを作成してhttp公開するのが便利です。

```shell-session
$ createrepo /<build_dir>/<tmp_dir>/deploy/rpm
```

上記で作成したリポジトリディレクトリを、ApacheやらNginxやらお好きなもので公開します。

# ボード側の設定

公開したリポジトリを利用するために、ボード側には最低限以下の設定が必要です。
設定ファイル(.repo)の名前はなんでもよいです。

```shell-session
$ mkdir /etc/yum.repos.d
```

```conf:/etc/yum.repos.d/yocto.repo
[yocto]
name=yocto
baseurl=http://<build machine>
gpgcheck=0
```

gpgcheckの設定については、以下の通り。

> この方法では、リポジトリの検証用のgpgkeyを無効にしているが、ローカル接続であれば問題ない。外部公開の場合は適切に設定すること。
> https://qiita.com/watatuki/items/4c3447a96309e19e7d5c

上記設定ができたら以下のコマンドを実行。

```
$ dnf makecache
```

正常に設定されていればリポジトリが読み込まれます。うまくいかない場合は設定ファイルや、リポジトリの公開設定などを見直してみてください。

# 動作確認

ここまでくれば、あとは

- パッケージのインストール

```
$ dnf install <package name>
```

- アップデート

```
$ dnf update
```

- 自分が公開したパッケージの確認

```
$ dnf list --available
```

などなど、コマンド一発でいろいろ簡単に行えるようになります。

# さいごに

組込み機器に限らずアップデートの機能はちゃんと作らないと苦労します(した)が、このように簡単に実装できてしまうのはすばらしいですね。

# (おまけ)バージョンを変えずにアップデートしたい

デイリービルドなどバージョンナンバーを変えずにアップデートしたいケースはあるかと思いますが、dnfでは同一バージョンの強制アップデートが(素直には)できません[^2]。
Yoctoではレシピのリビジョン設定をする変数が用意されているため、その値を変更することでdnfに異なるバージョン(リビジョン)のSWとして認識されるようになります。
https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-PR
ちなみに、自動でリビジョンを上げる方法もあるようです。
https://www.yoctoproject.org/docs/2.6/dev-manual/dev-manual.html#working-with-a-pr-service

[^2]: rpmコマンドを直接使用するとか、いくつか方法はある

# 参考

- [DNF Command Reference](https://dnf.readthedocs.io/en/latest/command_ref.html)
- [Yoctoでdnfを使う方法](https://qiita.com/watatuki/items/4c3447a96309e19e7d5c)
- [Use DNF Package Manager on a Yocto-built Development System](https://mindchasers.com/dev/yocto-dnf)
- [How do I create a repository](https://ask.fedoraproject.org/en/question/117343/how-do-i-create-a-repository/)
Syphonを利用してTouchDesignerで生成した動画をopenFrameworksで描画する方法



こちらは[TouchDesigner Advent Calendar 2018](https://qiita.com/advent-calendar/2018/touchdesigner) 12/9の記事です。

既存のopenFrameworksで作成したシステムの、映像生成部分だけTouchDesignerに移行する事を想定しています。

結論から言うと、TouchDesignerで生成した画像のoFへの取り込みは
Syphon Spout Out Top と [ofxSyphon](https://github.com/astellato/ofxSyphon) であっさり出来ました。

手順
1.TouchDesigner側から Syphon Spout Out Top を利用して画像を送信します。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/121076/52653e33-daba-8502-695d-2d27a96421af.png)
![2.png](https://qiita-image-store.s3.amazonaws.com/0/121076/6831f888-a5a0-db5b-d542-b91ba5ee1942.png)

2.openFrameworks側ではofxSyphonを利用して画像を受け取ります。
試しにアドオンのサンプルexample-ServerDirectoryを実行してみます。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/121076/674ad8b2-1675-f481-e6d4-95da3b85ef19.png)


受け取れた。

センサー類などをopenFrameworks側で制御している場合は、OSCでTouchDesigner側に値を送ってあげれば良いと思います。

TouchDesigner Advent CalendarなのにoFとの連携という変化球しか書けなかった...
早くTouchDesigner自体について書けるようになるために精進いたします。

参考 : 
Syphon
http://syphon.v002.info

OpenFrameworksでSyphonを使用する
https://qiita.com/tai_fukaya/items/2ac62442ffc004089126

TouchDesigner099（Mac版）でSyphon Spout In/Outが使えます。
http://blog.antymark.com/2017/01/touchdesigner099でsyphon-spout-inoutが使えます/
採用が恋愛なら、オンボーディングをしないのは釣った魚に餌をやらないということになっちゃうので整理してみた

おはようございます。[@oturu333](https://twitter.com/oturu333?lang=ja)と申します。
この記事は[モチベーションクラウド Advent Calendar 2018](https://qiita.com/advent-calendar/2018/mcs)の10日目として書いています。

タイトルちょっとおふざけしましたが、本気です。

入社を決めていただいた方と会社を恋愛のステップで例えるならお付き合いの始まり。「この人となら幸せになれるかもしれない！わくわく！でもちょっと不安もあるな」という状態なのかなと思います。
そしてオンボーディングがないというのは、お付き合いの直後に恋人を放置する、残念な彼、彼女ということになってしまいます。

入社をしていただいて、恋から愛に発展していくためのファーストステップ。大事にしたいですね。

モチベーションクラウドではもともとオンボーディングをまとめた資料がなく、改善活動の一環として最近まとめはじめているところです。
今回はその内容について書いていきます。

# 事前準備

- PCやアカウントなど事前に準備できるものを準備
- オンボーディングができるよう時間、人の確保

# 組織やプロダクトについてより深く知っていただく

プロダクトのエンジニアとしてジョインしていただく場合、携わるプロダクトはもちろん、それに関連する様々な情報を提供することで理解度がより深まり、業務へのモチベーションが高まると考えています。
そのために具体的に提供すべきと考えている情報

- 会社やプロダクトの歴史について
    - 会社がどのようなものを目指していて、このプロダクトはどのような意義を持って生まれ、現状どのようになっていて、どんな未来を目指すのか
- 配属先の組織について
    - 目指す未来に向け、どのような体制で何をしているのか
    - 今後どのようなことをしていこうと思っているのか
- プロダクトについての詳細
    - ロールや機能について
- 関連組織について
    - 他部署の人たちはどんな仕事をしていて、どのように協力しあって業務をしているのか

# お互いを知る

- 人の紹介
    - 入社いただいた方の自己紹介、一緒に働くメンバーの紹介
    - 関連部署で特に関わりのある人への紹介
- 座席表
- ウェルカムランチへのいざない

# 働く環境を知っていただく

- 業務で利用するツールの説明やアカウントの発行
    - Slackだったら必要なチャンネルへの招待など
- オフィスの案内
- 備品の使い方
- 勤怠連絡について

# 業務について知っていただく

- 存在するリポジトリについて
- 開発環境について
- ドキュメントの在り処
- 開発〜リリースまでのプロセスについて
- 各種環境について
    - 必要な権限発行なども含め
- Slack開発系チャンネルへの招待
- スキーマの説明
- ディレクトリ構成などコードについての説明

# 最後に

最初の不安を払拭したり、モチベーションを高めるためにも必要なオンボーディング。
PDCAを回しつつ、改善を続けていこうと思います。
laravelでサブクエリを使ってみた

# やりたい事
下記テーブルから30才未満のユーザーが所持している発売から1年以内の携帯を取得したい。

```sql:users_table
+----+---------------+-----------+-----+
| id | name          | phones_id | age |
+----+---------------+-----------+-----|
|  1 | XXX           | 1         | 25  |
|  2 | XXX           | 2         | 30  |
|  3 | XXX           | 3         | 21  |
+----+---------------+-----------+-----|
```


```sql:phones_table
+----+---------------+---------------------|
| id | number        | release_date        |
+----+---------------+---------------------|
|  1 | XXX-XXXX-XXXX | 2018-11-01 00:00:00 |
|  2 | XXX-XXXX-XXXX | 2017-11-01 00:00:00 |
|  3 | XXX-XXXX-XXXX | 2016-11-01 00:00:00 |
+----+---------------+---------------------|
```

# コード
```php:php
$lastYear = date("Y-m-d H:i:s", strtotime("-1 year"));
$data = Phone:where('release_date', '>', $lastYear)
    ->whereIn('id', function($query)
        {
            $query->select(DB::raw('phones_id'))
                  ->from('users')
                  ->whereRaw('age < 30');
        }
    )
    ->get();
```
Slackを研究室のラボメンに布教した話

# はじめに

研究室配属決まって，ライングループとか会話する場所が必要になりました。
メンバーの5/13がSlackのうまあじを知っている人間でしたので、
どうせならラボメンチャットはSlack使いたいよねという話になりました。

ただ、我が大学はリテラシー強い方からそこまで得意でも無い方もいるので
そういう人にいかにSlackを普及するか考える必要があり、以下のことを実行しました。
>1. 登録の煩雑さを無くす
2. 研究室ラボメンSlackの価値を高める
3. 他にチャットグループが出来ていないうちに

## 1.登録の煩雑さを無くす
Slackは細々とした登録がいらないとはいえ、招待する人にメアド貰って招待おくって、そこから招待された人が認証して
という面倒くさいステップがあり、ハードルとして存在します。

なので
Slackの[特定ドメインのメアドなら認証がいらない機能](https://get.slack.help/hc/ja/articles/201330256-%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AB%E6%96%B0%E8%A6%8F%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E3%82%92%E6%8B%9B%E5%BE%85%E3%81%99%E3%82%8B#u12513u12540u12523u12450u12489u12524u12473u12434u20351u12387u12383u26032u35215u30331u37682) と [招待Url発行機能](https://get.slack.help/hc/ja/articles/115004856503)を使うことにします。
することにより、
「メアド教えて」「メアドこれ」「招待おくったから確認して」....
などといった煩雑なステップをスキップすることができます。つよい。

## 2.研究室ラボメンSlackの価値を高める
[私はこうやってSlackを社内で流行らせました](https://www.slideshare.net/DATAHOTEL/slack-57873688)
こちらのスライドも~~社内SNSを牛耳るため~~社内SNSを改善するためにSlackを導入した方のまとめです。
ここにQiitaやはてぶ、Titterのタグ検索を垂れ流すチャンネルをあらかじめ作っておくことにより
**Slackの価値を高める**という強いハックがあったので取り入れることにしました。
[【Qiita】トレンドの新着のみをSlackに投稿する](https://qiita.com/uhooi/items/7ae555b5bf05c92fff74)
ここを参考に新着垂れ流す機能を作りました。

## 3.他にチャットグループが出来ていないうちに
**力技。**
他にチャットグループが出来ていないうちに過半数にとりあえず導入させることにより、
とりあえずラボメンに話をしたいならここ、という雰囲気を作ることに成功しました。

また、大学の研究室なら教授を、職場に導入なら上司を、といった様に
偉い人に旨味を伝え説得するのが有効な手段でもあります（当たり前ですが・・・。）


## 結果
研究室配属されてから数ヶ月経ちました。
教授も巻き込みいい感じにSlack上でラボメンのやり取りを行う場所ができました。

また、日報ならぬ分報だったり、ラズパイとslack bot使ってなんかやってたりいい感じなので、このまま楽しくやっていきたいと思う。


明日は@waku_25 です。何を書いてくれるのか楽しみですね。
dbrで発行するSQLを確認する

`dbr.NewBuffer()`で取得したバッファから、プレースホルダー付きSQLとプレースホルダーにセットする値が確認できる。
因みに`undefined: strings.Builder`のエラーになる場合は`go version`を`1.10`以上にアップデートしてください。

```sample.go
package main

import (
	"fmt"

	"github.com/gocraft/dbr/dialect"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gocraft/dbr"
)

func main() {
	// エラー処理は省略
	conn, _ := dbr.Open("mysql", "user:pass@/example", nil)

	sess := conn.NewSession(nil)
	// userID = 1で検索するSQL
	stmt := sess.Select("*").From("users").Where("id = ?", 1)

	buf := dbr.NewBuffer()
	stmt.Build(dialect.MySQL, buf)

	fmt.Println(buf.String()) // SELECT * FROM users WHERE (id = ?)
	fmt.Println(buf.Value())  // [1]
}
```
Hexoテーマ作成のためのデータ構造概説

この記事は JavaScript Advent Calendar の9日目です。
昨日は @stken2050 さんの[30分でわかるJavaScriptプログラマのためのモナド入門](http://kentechdoc.blogspot.com/2018/12/30javascript_4.html)でした。

---

最近[とあるサイト](https://suzukigu.me)をHexoで構築し直したので、オリジナルテーマを作成する際によく参照するデータ構造などを自分用メモとして公開しようと思います。

一昔前ならWordpressで構築するようなサイト構成ですが、Hexoなどの静的サイトジェネレーターで構築することで配信時には静的サイトの配信のみで済むというのがすごくイケてると感じました。

## 前提

- Hexo 3.7.0

## よく使うデータ構造

### 全ページ共通

|データ|説明|
|-----|----|
| config | `_config.yml`の情報を保持している |
| config.title | `_config.yml`内で`title: サイト名`のように定義した値が取得できる |
| site | サイト全体の情報を保持している |
| site.posts.data | 全投稿記事の情報。順序は不定。Documentオブジェクトで格納 |
| site.posts.length | 全投稿記事数 |
| site.categories | カテゴリ情報？ 使っていないのでよくわからず |
| site.tags | タグ情報？ 使っていないのでよくわからず |

### 投稿記事共通（Documentオブジェクト）

Documentオブジェクトとして共通化されている。各記事ファイルの冒頭に以下のようにヘッダ情報として記載した値はすべて格納されている。

```
---
title: ブログ始めました
date: 2018-12-08 22:54:10
---
```

|データ|説明|
|-----|----|
| title | ファイル冒頭部記載の記事タイトル |
| date | ファイル冒頭部記載の投稿日。`moment("記載の日付")`のようにmoment.jsの利用を前提としている |
| source | プロジェクトルートからのファイルパス |
| layout | 適用されているレイアウト |
| raw | ヘッダ部を含めたHTML化前の全文 |
| _content | ヘッダ部を除いたHTML化前の全文 |
| content | HTML化された全文 |
| excerpt | `<!--more-->`を利用したときにHTML化された前半部分。`<!--more-->`を使わない記事では空となる |
| more | `<!--more-->`を利用したときにHTML化された後半部分。`<!--more-->`を使わない記事では全文が入る |
| canonical_path | `posts/20181208/ブログ始めました/index.html`のようにルートからのファイル名を含むパス。正式なパスとしてはこれを使うべき？ |
| path | `/posts/20181208/ブログ始めました/`のようにルートからのパス |
| permalink | `https://suzukigu.me/posts/20181208/ブログ始めました/`のように通信プロトコル指定からのフルパス |
| tags | タグ情報？ 使っていないのでわからず |
| categories | カテゴリ情報？ 使っていないのでわからず |

### index

- `/posts`をインデックスとして構築
- デフォルトの`hexo-generator-index`は自由度が低いので`hexo-generator-index2`を採用
  - ジェネレーターを使わないと「新しい順に5投稿分表示」といった部分を自前で実装しないといけないので面倒

|データ|説明|
|-----|----|
| page | ページ情報。インデックスジェネレーターを利用しないとundefinedになる |
| page.total | 全ページ数 |
| page.current | 現在ページ |
| page.posts.data | ページ内の投稿記事情報。`_config.yml`の`index_generator.order_by`で指定したソート順で格納される。Documentオブジェクトで格納 |
| page.posts.length | ページ内の投稿記事数。`_config.yml`の`index_generator.per_page`で指定した件数まで格納される |
| page.prev_link | 前ページがあれば前ページのパス。なければ空 |
| page.next_link | 次ページがあれば次ページのパス。なければ空 |
| page.canonical_path | `posts/index.html`のようにルートからのパス |

### archive

- `hexo-generator-archive`を利用（デフォルト）
- アーカイブ単位は`年`, `月`で設定

|データ|説明|
|-----|----|
| page | ページ情報。indexで提供されていたデータはarchiveでも同様に含まれる |
| page.posts.data | ページ内の投稿記事情報。`_config.yml`の`archive_generator.order_by`で指定したソート順で格納される。Documentオブジェクトで格納 |
| page.posts.length | ページ内の投稿記事数。`_config.yml`の`archive_generator.per_page`で指定した件数まで格納される |
| page.year | ページに含まれる記事の投稿年 |
| page.month | ページに含まれる記事の投稿月 |

### 投稿記事

- `https://suzukigu.me/posts/20181208/ブログ始めました/`などにアクセスした場合

|データ|説明|
|-----|----|
| page | ページ情報。ただし他と異なり`page` = `Documentオブジェクト`となっている |
| page.prev | 前の記事のDocumentオブジェクト |
| page.next | 次の記事のDocumentオブジェクト |

---

テーマを作成する際にはこのあたりの情報が必須なのですが、公式ドキュメントにも詳しい記述を見つけられなかったため苦労しました。

Hexoのカスタムテーマ作ってみようかな、という方の参考になれば幸いです。

明日は @wonton14 さんの [「演算子の実行順」](https://qiita.com/wonton14/items/f7aa10302a62a865616d) です。

---

書き終えて思ったけどJavaScript要素がほとんどないな……。
Gitの操作を快適にする便利ツール「tig」

[TOWN Advent Calendar](https://qiita.com/advent-calendar/2018/town) 2018 10日目の記事です。

開発をする上でどの場面でほぼ必ず使う、Gitの操作をより快適にすることのできるツール「tig」の紹介をできればと思います。「tigってなんぞや？」って思っている方、「いやいやそんなの知ってるよ」っている方のどちらかに分かれるかと思います。今回の記事は前者の方向けのための記事なので、その辺はご了承ください😭


##tigって何？
簡単に言うと、gitで行ったりする「add」「diff」「commit」などを簡単かつ、見やすく快適に行うことのができるGitクライアントです。私はよくtigを使って開発する際に変更した差分や、前回のコミットで変更した内容をtigで見たりしています。

##インストール方法
＊windowsでのインストール方法もあるかと思いますが、今回はmacでのインストールを操作を全体に書かせていただきます。

homebrewからtigをインストールします。
`$ brew install tig`

##使用方法
以下のコマンドでtigが起動します。
`$ tig`

起動すると、メインビューと呼ばれる画面に映ります。メインビューにはコミットの一覧が表示されます。
![スクリーンショット 2018-12-10 1.39.05.png](https://qiita-image-store.s3.amazonaws.com/0/234233/6c91dc05-247c-41be-4bda-5f9b52c98416.png)

###差分を確認する(git diff)
メインビューで中で変更した差分を確認したいときは確認したい物を選択している状態で「Enter」を押すと中の詳しい内容が確認することができます。

赤い文字で書かれている部分を削除されたコード、緑の文字は反対に加えられたコードになります。

![スクリーンショット 2018-12-10 1.59.53.png](https://qiita-image-store.s3.amazonaws.com/0/234233/33d82306-160a-1006-de29-e0b402b98a5a.png)



###ファイルをステージにあげる（git add）
tigを起動した状態で `s` を押すと「ステージビュー」に移動します。

「ステージビュー」に移動すると以下のような画面表示になります。
![スクリーンショット 2018-12-10 1.46.04.png](https://qiita-image-store.s3.amazonaws.com/0/234233/86b6e0c6-9645-4873-855d-743483c197cc.png)

以前のコミットの情報を元にソースコードが変更されたか、されていないかを認識しています。以前のコミットから内容が変更されると、以下の部分に変更されたファイルの名前が表示されます。いわゆるアンステージ部分です。
>Changes not staged for commit:

変更したファイルをステージに持っていゆきたい場合はファイルを選択した状態で `u` を押すと以下部分のステージに移動させることができます。
>Changes to be committed:

逆にアンステージに持ってゆきたい場合も同様に選択して `u`　を押すことでステージからアンステージい移動させることができます。


 

よく使う部分をお話ししましたが、他にも「コミット」だったり、「ブランチ移動」など他にもtigでできることはたくさんあるので、公式ドキュメントだったり他の人が書いたqiitaの記事もとてもわかりやすく書かれていたので、ぜひそちらも参考にして見てください。