OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeでSuaveを始める

# Suaveとは？

https://suave.io/

F#用のウェブアプリケーションフレームワークです。ASP.NET上ではなく、独自のウェブサーバーを使っているようです。Githubのビルド手順を見ると、Libuvが必要なようなので、Libuvを使って構築されているのでしょうか？Nodeっぽいですね。

# VSCode + Ionideのインストール

VSCodeとIonide(F#用のプラグイン)をインストールします。

# Suaveプロジェクトの作成

IonideにSuaveプロジェクトを作成する機能が入っています。

CTRL+SHIFT+Pを推して、コマンドパレットを出します。

![20171025_01.png](https://qiita-image-store.s3.amazonaws.com/0/20734/fd5989de-2e49-f4f3-e224-613b0dec9a60.png)

suave applicationを選択し、コマンドパレットに表示されるウィザードに従って作成します。

![20171025_02.png](https://qiita-image-store.s3.amazonaws.com/0/20734/17fde064-2f29-92d0-1bd0-8c446920041d.png)

project directoryはプロジェクトが生成されるフォルダ、project nameはプロジェクトの名前を入れます。
(私はproject directoryを空、project nameに適当な名前を入れて作成しました。その場合、現在VSCodeで開いているフォルダにproject nameのフォルダが生成されました。)

生成後、プロジェクトの作成がバックグラウンドで動いているので、待ちます。終わったらVSCodeの通知経由で作成が完了したことがわかります。

で、ここでさっくり実行したいところなのですが、どうも一度依存ライブラリをリストアのようなことをする必要があるようです。

プロジェクトを生成したフォルダに有る、build.cmdをコンソール(VSCodeではCTRL+@で開けます)から実行します。そうすると必要なライブラリが全てダウンロードされ、初回ビルドが走ります。

最終的に次のようなフォルダ構成になります。

![20171025_03.png](https://qiita-image-store.s3.amazonaws.com/0/20734/51d8305a-157e-b20b-ef11-011e3826325a.png)

ここまで来たら、あとはコマンドパレット経由で、F# Run Default Projectを実行し、exeが実行されるのを待ちます。

![20171025_04.png](https://qiita-image-store.s3.amazonaws.com/0/20734/f72340d2-a56e-aa4a-2688-5d52b19e3dd2.png)

localhost:8080にアクセスして、Hello World!と表示されたら成功です。
DataBindingで値を自動で画面へ反映する

# サマリ
簡単に書くと、自動でBindしたい値のgetterに`@Bindable`アノテーションを付けて、View側で**変数を**指定してあげるだけです。

# サンプルコード
## Bindされるモデルクラス
```java:SampleModelClass.java
public class SampleModelClass extends BaseObservable {
    private String text;

    @Bindable
    public String getString() {
        return text;
    }

    public void setString(String str) {
        text = str;
        notifyPropertyChanged(BR.text);
    }
}
```

### extends BaseObservable
まずは1行目の`extends BaseObservable`です。
これをすることで、値に変更があったことを通知できるようになります。

### `@Bindable`
getterクラスに`@Bindable`アノテーションを追加することで、値が変更された変数をBindできるようになります。

### notifyPropertyChanged
setterクラスでこれを呼ぶことにより、値が変更されたことを実際に通知(notify)します。

## View側
```xml:SmapleView.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="model"
            type="net.furusin.www.sample.model.SampleModelClass" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{model.text}" />
    </LinearLayout>
</layout>
```

### android:text="@{model.text}"
今回はTextViewにBindしてみます。
注意は
**「`SampleModelClass#getString()`を呼ぶのではなく`SampleModelClass.text`とメンバ変数を直接指定する」**
ということです。

私は「値を取得するんだからgetterを呼ぶに決まってんじゃーん！」と思い込んでたのでハマりました。ご注意ください。

以上です。
git 先行リポジトリを後追いで作られた本番リポジトリに丸々移行したい

##経緯##
共同開発用のリポジトリ(本番)が用意してなく個人用のリポジトリ(先行)で開発を進めていた。
気づいたら共同開発用のリポジトリがいつのまにかできていた。
それもコミット済み。。　
だとすると自分のリポジトリをforkできない？？？？(できたのかも知れない)  

コミットログは両方残したいし、どうすればいいんだーってなった時にたどり着いたの下の記事  
[Qiita - GitHub 別リポジトリに push する方法](https://qiita.com/tak74/items/b0d1cc92fd172468fbf3)　　

>3)```$ git remote add torikomi_repo https://github.com/moto/torikomi_moto.git```
取込元をremoteに登録

追加したい個人リポジトリを取り込みたい共同開発用のリポジトリのリモートにすれば良いのかと実行。
source treeで見ると枝が繋がっていないだと。。。


##結論##
結局そこからチェリーピックを個人用にコミットした回数分(約100回)しました。。
絶対もっとスマートなやり方があると思う。。
しかも別リポジトリからのチェリーピックはsource treeではできないということで無知さに自分が情け無い。。。
ターミナル怖い。。
要素のテキストを取得する（子要素のテキストは除く）

## Get text in an element except its children

以下のようなHTMLからulのtextを取得したい場合、

```html
<ul id="target">
始
    <li>続</li>
    <li>終</li>
余
</ul>
```

こう書くと

```js
const selfText = document.getElementById('target').textContent;
console.log(selfText); // -> '始    続    終余'
```

子要素(li)のテキストまで取得しちゃいます。それがいらない場合、こう書く。

```js
const selfText = Array.from(document.getElementById('target').childNodes)
    .filter(e => e.nodeName == '#text')
    .reduce((a,b) => a + b.data, '');
console.log(selfText); // -> '始        余'
```
reduceの第二引数が地味に重要です。これを忘れると内部関数が引数のプロパティやキャスト結果を利用する場合、めんどくさくなります。

大抵は取得したいテキストがHTMLツリー上で特定の位置なり、id/classで指定できると思いますが、ふと困ったので備忘録メモ。
大容量ファイルをgit管理したくなったのでgithubの容量の上限を調べてみた

githubで大容量のファイルを管理したくなったのでどのくらいの容量までいけるのか調べてみました。

[What is my disk quota?](https://help.github.com/articles/what-is-my-disk-quota/)

こちらの記事に書いてあります。

## （通常の）githubの容量制限

* リポジトリの総容量は、1GB以下にするようおすすめ(recommend)されている
* 1GBを超える場合には、容量を減らすように丁寧にお願いするメールがとどくかもしれない
* 1ファイルについては、100MBの厳格な制限(a strict limit)がかけられている

## 大容量ファイル、リポジトリを扱いたくなったらどうすればよいか？

上記の容量を超える場合には、[git lfs](https://git-lfs.github.com/)を利用して、[Purchasing additional storage and bandwidth for a personal account](https://help.github.com/articles/purchasing-additional-storage-and-bandwidth-for-a-personal-account/)<-このページに書かれている方法でストレージを購入しましょう。
スプラトゥーン2のChrome拡張を作ってみた。

ikaWidget2とか使ってると、欲しいギアが来ても見逃すのでなんとかしようと思った。
そこで一番立ち上げっぱなしにしてることが多いChrome拡張（Chrome Extension）でギアの確認＋通知を作ってみた。
ついでにTypeScript触ったことないし使ってみた！

##Chrome拡張ってどう作るの？
この辺を参考に色々見てみた。

- [Chromeのオリジナル拡張機能を開発しよう（ソースコードあり）](https://liginc.co.jp/web/tool/browser/163575)
- [Chrome拡張の開発方法まとめ　その1：概念編](https://qiita.com/edit-mode/items/26d7a22233ecdf48fed8)

とりあえずわかったこと。

1. manifestファイル＋HTML＋CSS＋JSで作れる。→Web開発者なら多分作れる！
1. 機能によって3種類のパターンがある。
    3. Browser actions
    4. Page actions
    5. Override Pages

なんか作れそうな気がする！
今回はギアの表示をしたいのでBrowser actionsで作る。

##世の中便利なものがある
1から作ってると結構しんどい…
探してると[generator-chrome-extension-kickstart](https://github.com/HaNdTriX/generator-chrome-extension-kickstart)なるものがあった。そしてそこからフォークされた[generator-chrome-extension-kickstart-typescript](https://github.com/mazamachi/generator-chrome-extension-kickstart-typescript)を発見。
TypeScriptを使ったことがなかったのでgenerator-chrome-extension-kickstart-typescriptを使うことに決定。

##generator-chrome-extension-kickstart-typescript
インストールと実行

```bash
$ mkdir chrome_extension
$ cd chrome_extension
$ npm install -g yo generator-chrome-extension-kickstart-typescript
$ yo chrome-extension-kickstart-typescript
```

対話型で拡張の機能を指定していく。
<img width="1169" alt="スクリーンショット 2017-10-25 0.55.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/164059/14173a9a-29a0-9e67-c121-ccfceb87552b.png">

おっさんが表示されたらOK。
<img width="360" alt="スクリーンショット 2017-10-25 0.56.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/164059/8495cd2e-f84e-a809-6bd1-8128c23a6a75.png">

この時点でこんなフォルダ構成になっている。

```
/app
|--_locales
|  |--en
|     |--messages.json
|
|--fonts
|  |--.gitkeep
|
|--images
|  |--icon-128.png
|  |--icon-16.png
|  |--icon-19.png
|  |--icon-38.png
|
|--manifest.json
|
|--pages
|  |--options.html
|  |--popup.html
|
|--scripts
|  |--background.ts
|  |--options.ts
|  |--popup.ts
|
|--styles
   |--options.scss
   |--popup.scss
```

ビルドするとdist/に出力される。

```bash
$ gulp
#または
$ gulp --watch
```

chromeの拡張機能管理ページから読み込むと拡張機能におっさんのアイコンが追加される。
<img width="783" alt="スクリーンショット 2017-10-25 1.06.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/164059/594d7423-b103-bd09-f36a-be62b078f1d1.png">

##実装してく
あとはひたすらHTMLとCSSでレイアウト、JS(TypeScript)で処理を作っていく。

- Option Pagesで通信、通知をする場合、manifestファイルに許可が必要。

```json
"permissions": [
  "notifications",
  "https://<URL>"
]
```
- Typescript単体だと使いにくい
    - Notificationがinterfaceしか無い？
    - GoogleAnalyticsのga()が使えない？
    - ~~小規模だと型がうざい~~

このあたりはTypeScriptが使いこなせてないだけな気がする。Angularとか使えたらもう少し楽そう。

##Google拡張のPublish
- 初回登録料で500円かかる。ある程度の品質を担保するためだから仕方ない。
- ストア用の画像を用意する必要がある。指定のサイズじゃないとエラーになる。ここはできれば改善して欲しい…
- 一度公開すると、バージョンが同じ場合はエラーになる。

こんな感じで[SplaWidget2](https://chrome.google.com/webstore/detail/splawidget2/lilbiojjhobjjdifegpbndkmdjjbghdp)を公開。（1は存在しない）

<img width="354" alt="スクリーンショット 2017-10-14 17.24.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/164059/2c22fd31-fb9d-ad94-d9a5-ee169a8bc0a7.png">


##感想
Web系の知識だけで作れるので非常にお手軽。今後色々作っていきたい。
フレームワーク組み込めたらUIをもっとよくできるかな？
PublishするときにGAの設定できるけど数値がどこのPVなのか分からん。
Amazon Rekognition でオブジェクトとシーンの検出をしてみる


ローカルPC内の画像を対象にした実装とS3に入っている画像を対象にした実装


```python
#!/usr/bin/env python                                                                                                                                                                                                                                                           
#-*- coding: utf-8 -*-                                                                                                                                                                                                                                                          

from boto3 import client

def local_image_rekognition():
    """ ローカルPC内のファイルを指定する場合                                                                                                                                                                                                                                    
    """
    fd = open("[ファイル名]", "rb")

    rekognition = client("rekognition", region_name='us-west-2')

    response = rekognition.detect_labels(
        Image={
            'Bytes': fd.read()
        },
        MaxLabels=128
    )

    print(response)


def s3_image_rekognition():
    """ S3内のファイルを指定する場合                                                                                                                                                                                                                                            
    """
    rekognition = client("rekognition", region_name='us-west-2')

    response = rekognition.detect_labels(
        Image={
            'S3Object': {
                'Bucket': '[バケット名]',
                'Name': '[ファイル名]',
            }
        },
        MaxLabels=128
    )

    print(response)


def main():
    """                                                                                                                                                                                                                                                                         
    """
    s3_image_rekognition()


if __name__ == "__main__":
    """                                                                                                                                                                                                                                                                         
    """
    main()
```
C++でbison(パーサジェネレーター)を使う

コンパイラを作るにあたり構文解析(Parse)処理は要です。自分でゴリゴリと処理を書く方が最も柔軟ですが、それはそれでなかなか大変です。[Palan](https://qiita.com/tosyama/items/8d25a1456afbafe40658)では、先人の知恵bisonを使って構文解析器を生成しています。

# bisonとは
GNU版yaccです。C/C++/Javaの構文解析器を生成できます。入門としてはtoru0408さんの投稿が分かりやすいので分からない方はそちらをどうぞ。
→ [言語を作る！bisonとflexを使ってみた](https://qiita.com/toru0408/items/483c77cb76198d4c6ceb)

# C++で使いやすい構文解析器を生成する
bisonはC++をサポートしていますが、ネットではC言語での例がほとんどで、ググってもなかなかC++のよい例はあまり落ちてません。Palanではbisonを使ってC++コードの生成していますので、C++化のノウハウを紹介します。参考になるドキュメントは基本[Bisonの正式マニュアル](https://www.gnu.org/software/bison/manual/html_node/C_002b_002b-Parsers.html#C_002b_002b-Parsers)です。リアルなコードをみたい方は[Palanのソース](https://github.com/tosyama/palan/blob/master/src/ast)を覗いてください。

C++対応するには、まず定義ファイルを作ります。Cだと拡張子.yですが、C++の場合は.yyにします。拡張子によって生成ファイルの拡張子も変わりますが、気に入らなければコマンドライン-o オプションで出力ソースファイル名を指定できます(ヘッダ名は指定不可)。その中でbisonのスケルトンをC++用のスケルトンを指定します。任意のクラス名も指定できます。また、namespaceもデフォルトだとyyになってしまうので適切な名前を指定します。
※ namespaceを無名にしたかったのですができませんでした。

```cpp:PlnParser.yy
%skeleton "lalr1.cc"
%require "3.0.4"
%defines
%define parser_class_name {PlnParser}
...
%define api.namespace {palan}
```
Cで書く場合は共用体でデータの受け渡しを行いますが、C++では宣言した型のインスタンスで受け渡しを行います。共用体も使えますが、C++のクラスを共用体で使うにはコンストラクタが使えないなど問題が多いです。型チェックもちゃんと働いて使いやすいので、共用体は使わないようにしましょう。下記のようにapi.value.typeにunionの代わりにvariantを指定して、tokenやtype毎に<>内に型を宣言すればよいです。

```cpp:PlnParser.yy
%define api.value.type	variant

%token <int64_t>	INT	"integer"
%token <uint64_t>	UINT	"unsigned integer"
%token <string>	STR	"string"
...
%type <vector<PlnExpression*>>	arguments
%type <PlnExpression*>	argument
```
## 呼び出し方
bisonは字句を字句解析器(Lexer)から受け取る必要があります。受け取る関数についてはCと変わらずグローバル関数yylex()ですので、宣言が必要です。ここだけはC++っぽくないのですが、クラス化されたLexerを使用する仕組みは提供されています。その仕組みについてはまたの機会に。。

```cpp:PlnParser.yy
%code
{
...
int yylex(palan::PlnParser::semantic_type* yylval);
}
```

yylex関数は戻り値としてtokenの種類と、tokenのインスタンスを返す必要があります。tokenの種類についてはbisonから出力されるPlnParserのヘッダに定義されています。インスタンスについては、引数に対してbuild<型名>()を使って値をセットできます。

```cpp:lexer.cpp
#include "PlnParser.hpp"

int yylex(palan::PlnParser::semantic_type* yylval)
{
...
    // 整数の場合
    yylval->build<int64_t>() = std::stoll(yytext);
    return PlnParser::token::INT;
...
}
```

parse()メソッドでパース実行できます。

```cpp:main.cpp
#include "PlnParser.hpp"

int main()
{
...
    PlnParser parser;
    int res = parser.parse();
...
}
```
## vectorを使う際の注意
繰り返しの構文の部分ではSTLのvectorを使うことが多いと思いますが、アクションごとにインスタンスができるので、それごとに全コピーが発生するのは効率が良くありません。ここは、C++11のMoveセマンティクスを積極的に使いましょう!

```cpp:PlnParser.yy
arguments: argument
    {
        $$.push_back($1);
    }
    | arguments ',' argument
    {
        $1.push_back($3);
        $$ = move($1);   // $$ = $1では全コピーが発生。
    }
    ;
```

# つぶやき
C++のパーサーとしてはBoostのboost::spiritも検討しましたがコンパイルが遅すぎるのと、ミスった時のエラーメッセージがひどすぎて、本格的に使うのはやめた方がよさそうです。
bisonのノウハウまだちょっとあるけど、需要あるのだろうか。
WordPressで記事が公開されたタイミングで処理をする

# 経緯
とあるアプリでWordPressのコーポレートサイトの記事が公開されたら、アプリ通知を実行したいという要望があった。
その際に、「`save_post`にホックすれば余裕でしょ！」とか思ってたら痛い目を見たので、ここにメモ残しておきまする:pen_ballpoint:

ちなみにこの要望はのちになくなったのでこのソースコードは使われないことに....
供養も含めてメモメモ:disappointed_relieved::pray:



```php
/**************************************
/* 公開された際の通知処理
/* 以下の順で実施。(ステータスが公開に変わったか)->(カスタムフィールドを取得し、何かしらの処理を実行）
/* transition_post_status(is_published_now)=>wp_insert_post(do_something_on_published)
**************************************/
function is_published_now($new_status, $old_status, $post){
  // 投稿のステータスが「新規追加」または「下書き保存」または「レビュー待ち」または「予約投稿」から
  // 「公開」へ変わった際にflgを立てておく（save_postやedit_post/wp_insert_post ではステータスの変化がわからないため）
  global $is_publiched;
  if (($old_status == 'auto-draft'  || $old_status == 'draft'
       || $old_status == 'pending'  || $old_status == 'future')
    && $new_status == 'publish' && $post->post_type == 'post') {

      if (empty($is_publiched) && $old_status == 'future')
      { // 予約投稿の際、wp_insert_postは呼び出されないので、ここで呼ぶ
        hoge($post);
      }
      else{
        $is_publiched = true;
      }
  }
  else {
    if (!$is_publiched) $is_publiched = false;
  }
}
add_action('transition_post_status', 'is_published_now', 10, 3);

// 投稿に変更があり、かつ公開ステータスとなった際に実行
// （カスタム項目が取得できない関係上、transition_post_statusでは処理ができない為wp_insert_postを利用する。(save_post/edit_postも不可)）
function do_something_on_published($post_ID, $post){
  global $is_publiched;
  if ($is_publiched){
    hoge($post);
    $is_publiched = false;
  }
}
add_action('wp_insert_post', 'do_something_on_published', 100, 2);

function hoge($post){
 //ここに記事が公開されタイミングでしたい処理を描く。
}
```


参考サイト様。
感謝：
https://routecompass.net/twitter/
DropboxAPIの利用（アカウント認証）

昨日に引き続き、DropboxのAPIを触ってみました。
今回は、アカウント認証に関して載せます。

##必要な用意
下記の記事を参考に以下を行っておきます。
https://qiita.com/d-kawahara/items/e083efb9a641124b3716

・開発登録（appkeyの取得）
・SDKのインストール
・info.plistの項目追加

##実装
今回は、アプリ起動時にアカウント認証を行うようにします。
以下のコードでアプリ側での認証を行うことができます。

```Objective-c:AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 取得したappkeyを登録します。
    [DBClientsManager setupWithAppKey:@"取得したkey"];

    return YES;
}

// ログイン処理後、設定したschemeからのレスポンスを処理
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
  sourceApplication:(NSString *)source
         annotation:(id)annotation
{
    DBOAuthResult *authResult = [DBClientsManager handleRedirectURL:url];
    if(authResult != nil){
        if(authResult.isSuccess){
            // 成功
            NSLog(@"ログインに成功しました。");
        }else if(authResult.isCancel){
            // キャンセル
            NSLog(@"ログインをキャンセルしました。");
        }else if(authResult.isError){
            // 失敗
            NSLog(@"ログインに失敗しました。");
        }
        return YES;
    }
    return NO;
}

```


```Objective-c:ViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 個人用アカウントの認証状態を確認
    if (!DBClientsManager.authorizedClient) {
        [self auth];
    }
    
}

// 認証処理をリクエスト
- (void)auth {
    [DBClientsManager authorizeFromController:[UIApplication sharedApplication]
                                   controller:[[self class] topMostController]
                                      openURL:^(NSURL *url) {
                                          [UIApplication.sharedApplication openURL:url
                                                                           options:@{}
                                                                 completionHandler:nil];
                                      }];
}

+ (UIViewController*)topMostController {
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    
    return topController;
}
```

##実行
viewDidLoadにて認証をリクエスト後、以下の画面が立ち上がります。
※このとき、iPhoneにDropboxのアプリが入っていれば、アプリの、入っていなければ、webサイトの認証画面が立ち上がります。

![Simulator Screen Shot - iPhone 6 - 2017-10-25 at 21.21.39.png](https://qiita-image-store.s3.amazonaws.com/0/205256/5f04d9ce-d2de-3cf3-83c8-221ba8e37d21.png)


ちなみに、以下でログアウトも行えます。

```
[DBClientsManager unlinkAndResetClients];
```

以上がDropboxAPIを使用したユーザー認証になります。
eccube3の基礎知識(知っておくと役に立つこと)

# はじめに

これからeccube3を使う方が知っておくと役に立ちそうなことを抜粋してみました。
開発の際の参考にしていただけたらと思います。

# 3系と2系は別物

eccubeの3系と2系は**ほぼ別物**と考えてもらっていいです。(そもそも、採用しているPHPフレームワークから違います[^1])
そのため、2系をやったことがあるからといって、3系はすぐに使えるわけではないことを留意していただけたらと思います。

# 公式ドキュメントについて

eccube3に関する基本的なドキュメントは下記に公式ページがあります。基本的な使い方は下記にあるので、適宜参照してみるのがよいかと思います。
http://doc.ec-cube.net/

# eccube3のカスタマイズ

- 開発・カスタマイズはプラグインを作って行う
 - 既存機能を拡張するにも、新しい機能を追加するにも、プラグインを作らなければいけません。例え、**数行のカスタマイズでもプラグインの作成が必要です**
 - ただし、静的なコンテンツを追加するだけであればプラグインを使わなくても可能です


- デフォルトのtemplateをいじる際は、app以下にコピーすることで使える
 - これは下記ドキュメントをみていただければと思います
 - http://doc.ec-cube.net/design_template#デザインのカスタマイズ時のファイル配置

# してはいけないこと

- **srcディレクトリ以下はいじらない**
 - eccube3のコアファイルが格納されているディレクトリです。下手にいじったら、動かなくなります。やむ終えない場合以外はいじらないようにするのがいいかと思います

- **vendorディレクトリ以下はいじらない**
 - 外部のライブラリがまとまってるディレクトリです。こちらもsrcディレクトリ同様、下手にいじったら、動かなくなります。こちらもいじらない方がいいかと思います

# 変更が反映されない

- 変更が反映されなければキャッシュを削除する
 - サーバー側のキャッシュが残っていることが多いです。特に、twigテンプレートの変更を加えて反映されてなければ、大体キャッシュが原因です

# エラー画面が表示された時

- ログを見ましょう
 - eccubeはログをデフォルトで下記のディレクトリにとってます
 - app/log/ディレクトリ
- フロント画面のログは"app/log/front_site_YYYY-MM-DD.log"にとってます
- 管理画面のログは"app/log/admin_site_YYYY-MM-DD.log"にとってます
- [エラー画面]とは、下記のような画面のことです↓
 ![スクリーンショット (55).png](https://qiita-image-store.s3.amazonaws.com/0/200242/0813a738-6985-e433-6682-70d3c4cfaa91.png)


# コードの書き方が分からない

- 開発に詰まったら配布のプラグインやsrcファイル以下のコードを見てみましょう
- プラグインやsrcコード以下は既に出来上がったコードなので、参考になるかと思います。
 - 例えば、公式のプラグインである「商品レビュー管理プラグイン」(https://www.ec-cube.net/products/detail.php?product_id=1065) などは参考になると思います

# 終わりに

他に「これとか基礎知識として知っとくと役に立つんじゃないか？」というものなどがございましたら、おっしゃっていただけたらと思います。また、間違いなどありましたらご指摘くださいませ。

[^1]: 3系はsilexというSymfony2 ベースのフレームワークを採用。対して、2系は独自フレームワークを採用
PolyfillとPonyfill

JavaScriptを書くにあたって、未だにブラウザによっては存在しない機能を考慮せざるを得ない状況が続いています。そこで取る対策として、PolyfillとPonyfillがあります。

# 気の抜けない、ブラウザごとの差

最近でこそブラウザは強制バージョンアップするものが増えてきましたが、もはやバージョンアップすることのないIE 11、そしてOSとセットでしかアップデートできないiOSのSafariなど、常に最新といかない環境も残り続けています。さらに言えば、JavaScript自体もECMA 201xというように、毎年バージョンアップし続けるので、ブラウザごとにそれをキャッチアップできるタイミングも違ってきます。

ということで、どこまで行っても「ブラウザごとの実装差」は残り続けることとなってしまいます。

# Polyfillのメリットと欠点

Polyfillとは、「標準となったメソッドが存在しない場合に、自分で供給してしまう方法」です。JavaScriptに加わる新機能の中で、文法ごと書き換わってしまうものはどうしようもないですが、新しい標準関数が増えた場合は、自分で`prototype`に書き足してしまうことも可能です。

なお、「Polyfill」という単語は、壁などの「隙間を埋める」ペーストの[Polyfilla](http://www.polycell.co.uk/product/polycell-advanced-polyfilla/)に由来しているとのことです。

Polyfillのメリットとしては、「本体コードを書き換えずに済む」ということがあります。足りない関数だけPolyfillを入れれば、残りのコードはそのままで、幅広いブラウザに対応できます。

ただし、Polyfillのデメリットとしては、いくつかあります。今までできたことをスッキリ書くような、ユーティリティ型のメソッドであれば、今ある機能で、仕様と全く違わぬ動きをさせることができます。一方で、新しく加わったものの場合、完璧にPolyfillできないこともあります。例えば、`WeakMap`の「キーがガベージコレクトされたら値も巻き添えになる」という動作は、JavaScript内で実現することができません。

そのように、「正式なメソッドと微妙に異なるPolyfill」は、他のライブラリと組み合わせた際に、思わぬバグのもととなります。

# Ponyfillという概念

そこで、「Polyfill」という単語を少し書き換えた「Ponyfill」という概念が登場します。これは、「Polyfillが暴れん坊なのに対して、ポニーのようにピュアな」もの、を意図しているとのことです。

実装自体はPolyfillと同様に自前のJavaScriptを用意はするのですが、それを標準オブジェクトに上書きするのではなく、全く別個の関数として使えるような形で用意しておく、というような手法です。

# 残酷な現実

で、実際のPolyfillライブラリを見ていると、存在しないブラウザにコードを追加するコードどころか、「**既存の実装のバグ**をチェックして、バグが存在する場合には自前コードに切り替える」ものすら存在していて、なんだか闇に片足を突っ込んだような気分になることもあります。


# 外部リンク

* [http://ponyfill.com/](http://ponyfill.com/)
ImageMapを送信してみた


# イメージマップとは
画像に1つ以上のリンク・テキスト送信のアクションを設定出来る送信方法
画面全体で一つのアクションを指定したり、場所で区切ってアクションを指定する事も可能

https://developers.line.me/ja/docs/messaging-api/reference/#anchor-66fcb7a0e9f4b2deb9eb2a0ace36ca6a4cc70e41


## 用意する事
画像を複数サイズ用意する必要があり、それぞれエンドポイントを用意する必要がある
~~これが面倒~~
単純に、それぞれのサイズの画像を用意して、ファイル名を指定されているサイズに合わせて変更すれば良いだけ

また、画像は`jpg`か`png`に限られる

ので、例えば、`https://baseurl/`に`1040`,`700`,`460`,`300`,`240`のサイズと名前で画像を設置すれば良いだけ


# 実装
公式のSDKを利用

line/line-bot-sdk-python: SDK of the LINE Messaging API for Python. 
https://github.com/line/line-bot-sdk-python

`/examples/flask-kitchensink/`
に `imagemap` の例は実装されていないものの、
`/linebot/imagemap.py`
に実装されている為、読み込んでSDKの記載にある通りに


## コード
（kitchensinkを元にしている想定）

```python
from linebot.models
+ MessageImagemapAction,ImagemapArea,ImagemapSendMessage,BaseSize,URIImagemapAction, MessageImagemapAction

imagemap_message = ImagemapSendMessage(
  base_url='https:/example.co/imagemap/',
  alt_text='this is an imagemap',
  base_size=BaseSize(height=1040, width=1040),
  actions=[
    URIImagemapAction(
      link_uri='https://www.walker-industries.co.jp/',
      area=ImagemapArea(
        x=0, y=0, width=520, height=1040
      )
    ),
    MessageImagemapAction(
      text='hello',
      area=ImagemapArea(
        x=520, y=0, width=520, height=1040
      )
    )
  ]
)

line_bot_api.push_message(event.source.user_id, imagemap_message)
```
C++でファイル変更を検知

openframeworksでシェーダーでライブコーディングしたり、デバッグのスピードを上げるためにファイルの保存を検知して、シェーダーをリロードできるようにしたいなと思って

# コード

``` c++:testApp.h
// デフォルトでは使えないのでヘッダーをインクルード
#include <sys/stat.h> // 注意点1

class testApp {
    ofShader shader;
    string shader_path; // シェーダーへの絶対パス

    struct stat stat_buf; // stat使うためのやつ
    time_t last_file_time; // ファイルの最終更新時間

    // 以下略
}
```

``` c:testApp.cpp
void testApp::setup() {
    shader_path = ofFilePath::getAbsolutePath("frag.frag", true); // 注意点2
    shader.load("default.vert", shader_path);

    stat(shader_path.c_str(), &stat_buf); // ファイル情報を取得
    last_file_time = stat_buf.st_mtime; // ファイルの最終更新時間の初期値

    cout << "last_file_time : " + ofToString(ctime(&last_file_time)) << endl; // 確認用 注意点3

    // 以下略
}

void testApp::update() {
    stat(shader_path.c_str(), &stat_buf);

    if (stat_buf.st_mtime != last_file_time) { // 更新されたかチェック
        cout << "shader changed" << endl;
        cout << "current_file_time : " + ofToString(ctime(&stat_buf.st_mtime)) << endl; // 確認用

        last_file_time = stat_buf.st_mtime; // ファイルの最終更新時間を更新
        shader.load("default.vert", shader_path); // シェーダーを更新
    };

    // 以下略
}

// 以下略
```

# 注意点

1. statはヘッダーをインクルードしないと使えません。
2. 絶対パスじゃないと動いてくれないので、oFのメソッド（ofShaderのロードでも使われてるやつ)使います。
3. ログに表示するときはstatのmtime使うと、人間が見られる形になります。

---

以上になります。訂正よろしくお願いします🙏

## 参考
[ファイルの状態を取得する | C言語入門講座](http://www.c-lang.net/stat/index.html)
Python上でShellに対してコマンド打ちながら結果をStringで拾う方法（パイプ対応付き）

#とりあえずソースコードはこちら
こいつらを使えばすべてString型でReturnされます。
ワイルドカード、\>とかのタイプのパイプには未対応です。



```{ConsoleInput.py}
# -*- coding: utf-8 -*-

#マルチパイプ処理もできるPythonコード。

import subprocess as sb
import sys

def S_InputConsole(CommandString):
    #コマンドを受け付けて、結果をStringで変換するコード
    
    #print("console In:" + CommandString)
    return sb.check_output(CommandString.split(" ")).decode("utf-8")


def InputPIPECommand(CommandString):
    
    #print("Console Pipe In: "+CommandString)
    #shell = TrueとなってるときはStringで打ち込んでもちゃんと読んでくれる。
    #shell = Trueとなっているときは、Shellに直打ちしているので、意図しないコードが発動した際は責任を持てません。
    #こいつにはワイルドカード,>,<,$(), 1>&2などすべての機能を使用可能
    #Tensorflowなど重い処理で結果をリアルタイムで出力してほしいときは、1>&2する。
    _execProcess = sb.Popen(
            CommandString,
            shell = True,
            stdin = sb.PIPE,
            stdout = sb.PIPE,
            stderr = sb.PIPE,
            ).communicate()[0]
    
    return _execProcess.decode("utf-8")
    
def S_InputPIPECommand(CommandString):
    #単一のパイプのみに対応する方法
    CommandList = CommandString.split("|")
    
    Exec1 = sb.Popen(CommandList[0].split(" "),stdout = sb.PIPE)
    Exec2 = sb.check_output(CommandList[1].split(" "),stdin = Exec1.stdout)
    
    return Exec2.decode("utf-8")

def S_InputMultiPIPECommand(CommandString):
    #１個以上のパイプに対応
    CommandList = CommandString.split("|")
    ExecNum=len(CommandList)
    CommandExecList =  []
    Execfirst = sb.Popen(CommandList[0].split(" "),stdout = sb.PIPE)
    CommandExecList.append(Execfirst)
    for CommandIndex in range(1,ExecNum-1):
        ExecProgress = sb.Popen(CommandList[CommandIndex].split(" "),stdin = CommandExecList[CommandIndex-1].stdout,stdout = sb.PIPE)
        CommandExecList.append(ExecProgress)
    
    ExecLast = sb.check_output(CommandList[ExecNum-1].split(" "),stdin = CommandExecList[ExecNum-2].stdout)
    
    return ExecLast.decode("utf-8")


        
```
S_InputMultiPIPECommandの方は、自動でパイプ数を計測して、自動でつなげてくれます。まぁまぁ便利。
#使用例

```{getlist.py}

jpglist=S_InputMultiPIPECommand('cat ./hogeimagelist.csv | grep .*JPG').split('\n')
#jpglistが欲しいときに。

jpglatestlist = S_InputMultiPIPECommand('cat ./hoge.csv | grep .*JPG | grep 2017-10-\d\d').split('\n')
#最近のJPGlistが欲しいときに。

Totalfilelist = S_InputConsole('ls -R /dataset/').split('\n\n')
for filelist in Totalfilelist:
    Directory = filelist.split(':')[0]
    for _file in filelist.split(':')[1].split('\n'):
        if re.compile(r'JP\w*G').findall(S_InputMultiPIPECommand('identify '+Directory+_file+' | grep Format.*\n')) != []:
            S_InputConsole('mv '+Directory+_file+' '+Directory+_file[:-4]+'.JPG')  
#GIF画像と名乗っている癖に実はJPGというのを炙り出すコード（イメージとしてテキトーに書いてるのであてにして使わないこと。）

```
どれもShellScriptで書けばいいんじゃね？って思う人も居るだろうが、
複雑なコードはPythonだと開発スピードがえらく速い上、rm -rしたいときにチェックできたり、安全装置を挟んだりできるので、慣れてない人にうってつけ。
他にも何かと使えたりする。例外処理もできるし。

結果はどうでもいいからリアルタイムで標準出力を出してほしいときは、shell=True設定で末尾に1>&2をつけてエラー出力すると端末でも見れます。

以後、使い回してお使いください。
NECの家庭用ルータがギガスイッチと1000Mbpsリンクに失敗する状況の回避法


どうしようもないバッドノウハウなので適当な箇条書きですがご容赦ください。

1. リンク速度インジケータのあるギガスイッチと、Atermをつなぐ。
    1. 今回のAtermは**WG1800HP2**、ギガスイッチはバッファローの**LSW4-GT-5NS**。
        1. **Atermシリーズには中身がNetBSDのとLinuxのがある**。WG1800HP2はNetBSDなのでLinuxな方にはこの問題はそもそも起こらないかもしれない。
        2. これらの製品それぞれは単体では優秀。繋ぐと下記の通りだが、回避できた状況を見るにお行儀がよろしくないのはルータ側でしょう
    2. もしインジケータがなかったら一足跳びに3へどうぞ。
2. 10秒以上かけてリンクアップするが、**何故か100BASE-TXが使われる**。
    1. Aterm側でWANポートに繋いであればモード選択が可能だが、1000BASE-Tは選べず100以下とオートしか選べない。
    2. 今回の環境においては後述の理由でWANポートは使わずLANポートとスイッチの接続を行なっているが、恐らくはWANポートでも同じように今回の方法が使えるでしょう。
3. SMB等ファイル転送なり、iperfなりすると、**本当に100Mbpsしか出なくて~~唖然とする~~**。

これに対して、

1. **FreeBSDマシン**と**1000BASE-Tに対応するUSBイーサネットアダプタ**を用意する
    1. 今回用いたUSBイーサネットアダプタはバッファローのLUA4-U3-AGT。~~高負荷がかかると3秒くらいで即死するので買ってはいけない~~
    2. オンボードやPCIeカードを用いた場合どうなるかは不明。試したら教えてください
    3. FreeBSDの代わりにLinuxなど他のOSを用いた場合も不明。
2. こいつらとAtermを繋ぐと、**オートネゴではやっぱり100BASE-TXでリンクする**。
    1. ケーブルはCAT6Aの細めのやつ。
    2. このときオートネゴに成功する環境においてこの先の手順を行った場合に上手くいくかは不明。どなたか試したら是非教えてください
    3. なお、この時**USBアダプタに付いている1000ランプは何故か点灯する**。~~嘘つきめ！~~
3. USBアダプタをFreeBSDマシンに繋いだタイミングでdmesg(8)に出る案内を元に、**ifconfig(8)で1000BASE-Tを直接指定する**。
    1. と、1000BASE-Tでのリンクに成功する。
    2. 失敗した場合はご愁傷様です。
4. USBアダプタからLANケーブルを抜き、**単にギガスイッチに繋ぎ直す**。
    1. 作業の性格上、抜いて挿すまでにあまり時間が空くと失敗すると思われる。気持ち素早く
5. **何故か1000BASE-Tでのリンクに成功する**。
    1. 即座にリンクし、速度もちゃんと出る。
    2. ~~危険な匂いのする~~ECOモードは切っておくことを推奨。
    3. なお、本件とは関係ないがJumbo Frames環境ではハブもLAN側に接続するのが好ましい。
        1. WAN側はブリッジモードであってもLAN側ジャンボフレーム透過設定の範囲外なのでその先に限って1500より大きいフレームが行かなくなって困る。
            1. L2でフレームドロップされると、L3のテクノロジであるPMTUDは無力になってしまう。~~憤死不可避~~
            2. **ssh(1)は繋がるけどそのままtop(1)かけるとぷっつん**したりする場合はこういうケースを想像すべし。
        2. そこにはJumbo Frames非対応の、例えばpiとかプレステとかnasneとかそーいうのを挿しておこう。
6. ~~NECにキレる。~~
    1. ~~と言っても、仮にサポセンに当たり散らしたとして「ハブ繋ぐようなヘンタイさんはお客様ではありません」対応は不可避なので内心で毒づくだけにしておくのを強く推奨~~
C++ Builder > ファイル処理検討 > 複数のプロファイルの切替え > _profファイルとdetailファイルでの読書き

```txt:動作環境
C++ Builder XE4
```

### 処理

複数のプロファイルに対して、以下の処理をする。

- プロファイル新規追加
- プロファイル切替
    - 保存はしない
- プロファイル削除
- プロファイル保存
    - 切替後の保存
- プロファイル詳細の保存

以下が関連する関数。自作のJSONの読書き処理を使用しているのだが、詳細は割愛する。

- Setting_load_profile()
- Setting_load_detail()
- Setting_save_profile()
- Setting_save_detail()
- Setting_delete_detail()

### code 

プロファイルと詳細の読書き処理は以下のようにした。

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DBXJSON.hpp> // for JSON
#include <IOutils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Setting_load_profile();
	Setting_load_detail(E_profile->Text);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Setting_load_profile(void)
{
        // 割愛
}

void __fastcall TForm1::Setting_load_detail(String profName)
{
        // 割愛
}

void __fastcall TForm1::Setting_save_profile(void)
{
        // 割愛
}

void __fastcall TForm1::Setting_save_detail(String profName)
{
        // 割愛
}

void __fastcall TForm1::Setting_delete_detail(String profName)
{
        // 割愛
}

//---------------------------------------------------------------------------

void __fastcall TForm1::B_addProfileClick(TObject *Sender)
{
	E_profile->Text = L"prof2"; // 新規プロファイル
	E_detail->Text = L"Default"; // デフォルト詳細に戻す
	//
	Setting_save_profile();
	Setting_save_detail(E_profile->Text);
}

void __fastcall TForm1::B_selectProfileClick(TObject *Sender)
{
	E_profile->Text = L"prof1"; // 既存プロファイル
	//
	Setting_load_detail(E_profile->Text);

	// 選択のみではプロファイル保存をしない
	// (保存せずに閉じた時に選択前のプロファイルに戻すため)
}

void __fastcall TForm1::B_deleteProfileClick(TObject *Sender)
{
	Setting_delete_detail(E_profile->Text); // 現在のプロファイルを削除 (例: prof1)

	E_profile->Text = L"prof2"; // 既存プロファイルに切り替え
	Setting_load_detail(E_profile->Text);

	Setting_save_profile();
}

void __fastcall TForm1::B_saveProfileClick(TObject *Sender)
{
	Setting_save_profile();
}

void __fastcall TForm1::B_saveDetailClick(TObject *Sender)
{
	Setting_save_detail(E_profile->Text); // 現在のプロファイルに保存
}


//---------------------------------------------------------------------------

```

### 関連

[C++ Builder > ファイル処理検討 > 複数のプロファイルの切替え > Setting.txtを経由する](https://qiita.com/7of9/items/5f1e5fcb752473ec9e1a)
にて考えていた処理よりはすっきりした。

JSON読書き処理のコードと組合せて、ある程度の動作確認は済んだ。

あとはUI処理の実装。
レシートの照合【Android編】

## 1.「Google API OAuth2.0のアクセストークン&リフレッシュトークン取得手順 2017年2月版」のrefresh_tokenが取得できるとこまで進める。
https://qiita.com/iwaseasahi/items/2363dc1d246bc06baeae

## 2.以下を実行してアクセストークンを取得する。
curl -v -X POST 'https://accounts.google.com/o/oauth2/token' -d 'grant_type=refresh_token&refresh_token={リフレッシュトークン}&client_id={クライアントID}.apps.googleusercontent.com&client_secret={クライアントシークレット}&redirect_uri=https://onimomo-test.firebaseapp.com/__/auth/handler'

```json
{
  "access_token" : "ya29.XXXXXXXXXXXX",
  "expires_in" : 3600,
  "token_type" : "Bearer"
* Connection #0 to host accounts.google.com left intact
}
```

## 3.アクセストークンを使用してAPIを実行する
```
curl https://www.googleapis.com/androidpublisher/v1.1/applications/jp.etimestech.onimomo/inapp/{アプリのパッケージネーム}/purchases/{設定した商品名}?access_token={アクセストークン}
```

## 4.以降、アクセストークンが切れたら**"２"**からやり直す

## 参考
●https://qiita.com/iwaseasahi/items/2363dc1d246bc06baeae
　Google API OAuth2.0のアクセストークン&リフレッシュトークン取得手順 2017年2月版
●https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5
　Google APIのAccess Tokenをお手軽に取得する
●https://ameblo.jp/principia-ca/entry-12071725733.html
　自動購読課金について【Android編】
Kotlin でコマンドラインの Hello World アプリケーション

## Kotlin のインストール

今回の環境は macOS なので Homebrew を使ってインストールする。

```
$ brew update
$ brew install kotlin
```

Kotlin のバージョンを確認。

```
$ kotlinc -version
info: kotlinc-jvm 1.1.51 (JRE 9.0.1+11)
```

## Hello World アプリケーションをつくる

hello.kt というファイルを作成し、以下のプログラムを記述する。

```kotlin
fun main(args: Array<String>) {
    println("Hello, World!")
}
```

kotlinc コマンドでコンパイルし、JAR ファイルを作成する。

```
$ kotlinc hello.kt -include-runtime -d hello.jar
```

kotlin コマンドを実行すると、「Hello, World!」と表示される。

```
$ kotlin hello.jar 
Hello, World!
```

JAR ファイルなので java コマンドでも実行できる。

```
$ java -jar hello.jar
Hello, World!
```

## Hello World スクリプトをつくる

hello.kts というファイルを作成し、以下のプログラムを記述する。

```kotlin
println("Hello, World!")
```

kotlinc に -script オプションを付けることで、コンパイルの手順を飛ばして、スクリプト言語のように実行できる。

```
$ kotlinc -script hello.kts
Hello, World!
```

## クラスを使う

message.kts というファイルを作成し、以下のプログラムを記述する。

```kotlin
class Message constructor(msg: String) {

  val msg: String

  init {
    this.msg = msg
  }

  fun puts() {
    println(msg)
  }
}

val m = Message("Hello, World!")
m.puts()
```

kotlinc -script で実行できる。

```
$ kotlinc -script message.kts 
Hello, World!
```

## 参考資料

- [Working with the Command Line Compiler \- Kotlin Programming Language](https://kotlinlang.org/docs/tutorials/command-line.html)
vueのテンプレート内で一時変数的なのを利用したい時

乱暴なやり方だと思っていて、他にいい方法があるか知りたい。
そもそもこういうことをやらないといけない設計に問題があるのかもしれない。

とあるテンプレート内で、自身のプロパティが保有するモデルインスタンスのメソッドをコールし、
その戻り値をテンプレート内で何度も繰り返し利用したくなった。
テンプレートを利用せず、renderメソッドを利用すれば解決できるんだけど、
テンプレートの記述量が多く、これをメソッドに落とすのはとてもしんどいし
可読性がしこたま悪くなる。
かといって、vueでは以下のようなテンプレート内での変数定義ができなさそう。

```html
<template>
  <div v-for="item in items" :key="item.id">
    {{var hoge = model.getSomeValueByItemId(item.id)}}

    <p>{{hoge}}</p>
    <p>{{hoge * 2}}</p>
    <p>{{hoge * 3}}</p>
  </div>
</template>
```

そこで仕方なく、「thisのメンバとして、一時変数的に入れちゃえばいいや。dataの中に入ればければ値のプロキシも発生しないしインパクトも少なかろう、、」、と
以下のようなことをやってみた。

```html
<template>
  <div v-for="item in items" :key="item.id">
    {{_hoge = model.getSomeValueByItemId(item.id)}}

    <p>{{_hoge}}</p>
    <p>{{_hoge * 2}}</p>
    <p>{{_hoge * 3}}</p>
  </div>
</template>
```

すると、代入している箇所で戻り値がそのままレンダリングされてしまった。そりゃそうだ。

で、以下のようにした。

```html
{{(_hoge = model.getSomeValueByItemId(item.id)) && null}}
```

こうするとレンダリング対象の変数は必ず一番右辺のnullになる。

やっておきながら、これだとテンプレート箇所になんだかよくわからんスキーマが隠れちゃって危ない気もしていて
こういう時にrenderメソッド利用時のように、templateタグや、v-forのブロックの中だけをスコープとした変数の定義ができるようにして欲しい。
テンプレートはできるだけプログラムチックな記述をさせないぞ、というvueの思想なのかなあ。
raspberry Piで使うSDカードのclean

#ぶつかった問題
Macに標準でついているソフト、「ディスクユーティリティ」でSDカードの中身を削除しようとしたんですけど失敗しました。なんか、がっつり消去するために上書きを何度も行うオプションを選択してもダメでした。

#利用した環境
Macです。OSはSierraで動作をしました。

#解決策
結局「SD Card Formatter」というソフトを利用したら一瞬で、一発で消せて、しかもキチンとraspberry Piで動作してくれました。
https://www.sdcard.org/downloads/formatter_4/

ちなみに、フォーマットオプション設定はクリーンフォーマットを選択しました。
Web上での単純作業を自動化するSeleniumの基本

![big-logo.png](https://qiita-image-store.s3.amazonaws.com/0/82763/00c4652b-ab1a-0403-e454-d6a2b07c1210.png)


Webサービスをブラウザ上でポチポチクリックするような単純作業は正直つらいと思います。
Seleniumを用いると、そのような作業を自動化することができます。
この記事では、Seleniumの基本的な使い方を紹介したいと思います。
具体的には
・事前準備
・ページの遷移
・テキストフィールドの入力
・ボタンのクリック
などです。
上記だけで完結する単純作業もあるのではないでしょうか。

環境はWindows、ブラウザはChromeを利用しています。


# 事前準備
下記からchromeのdriverをダウンロード。
https://sites.google.com/a/chromium.org/chromedriver/downloads

適当なフォルダに保存。


# ページの表示

```test.py
from selenium import webdriver

# 先ほどダウンロードしたchromedriverを読み込む
driver = webdriver.Chrome("./chromedriver.exe") 
driver.get("https://~~~")
```

すると、Chromeウインドウが自動で開き、ページに遷移します。

# テキストボックスへの入力

Seleniumでは、HTML内の要素（element）を`name`や`id`で指定し、
それに対してアクションをする、という書き方になっているようです。

下記の`email`の部分は、サイトごとによって異なります。
Chromeで右クリックし「検証」を押してソースコードを表示、
自分が操作したい要素の`name`や`id`をチェックしてください。
確認したところテキストボックスが`email`という要素だったので、`hoge@hoge.com`というテキストを入力しています。

```test.py
driver.find_element_by_name("email").send_keys("hoge@hoge.com")
```

また、入力フィールドをクリアするには、`clear()`があります。

```test.py
driver.find_element_by_name("email").clear()
```

# ボタンのクリック

idが"search_button"と設定されているボタンを選択し、それをクリックします。

```test.py
driver.find_element_by_id("search_button").click()
```

これを用いることで、ダウンロードボタンのクリックも可能になります。

# チェックボックスが選択されているかどうかの確認

```test.py
driver.find_element_by_id("check_box").is_selected()
```

チェックボックスをクリックするとon/offが入れ替わるため、
既にチェックされてるかどうか確認したのちに、`click()`を実行する必要がある場合に用います。

# ソースコードの表示

```test.py
driver.page_source
```

取得したのちは、`split()`などで適当に分割して扱うのが良いかと思います。


# その他
ブラウザでの操作は、実行してから応答があるまで時間がかかることがあるため、
コードとコードの間に`time.sleep(5)`などを設け、
適当な時間あけるのが良いかと思います。

また、実行中のブラウザをいじっていると、予期しないエラーを吐くかもしれないため、触らないほうがいいと思います。


# おわりに

単純作業は自動化して、他のことに時間使いたいですね。
このような自動化は、作業時間の変化によって、効果がわかりやすいのも達成感を感じやすくいいなと思いました。

誤りや、アドバイスなどがあったら教えていただけると嬉しいです。

なお、[自分のブログ](https://medium.com/music-and-technology/web%E4%B8%8A%E3%81%A7%E3%81%AE%E5%8D%98%E7%B4%94%E4%BD%9C%E6%A5%AD%E3%82%92%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%99%E3%82%8Bselenium%E3%81%AE%E5%9F%BA%E6%9C%AC-d908f2121776)の転載になります。
Boostnoteのデータが消える(ように見える)バグが起こった原因

Boostnoteのメンテナーのsosukesuzukiです。[Boostnote](https://github.com/BoostIO/Boostnote)のv0.8.15にて、一部のユーザーのデータが全てあるいは一部が消える（ように見えるバグ）が発生しました。現在では、このバグの対処法が[Boostnoteの公式ブログ](http://boostnote.hatenablog.com/entry/2017/10/24/124650)にて掲載されていますが、このバグはElectronを使用するアプリケーションでは発生する可能性が往々にして存在するので、Electronアプリケーション開発者の皆様の目にこの記事が届いてこういったバグが発生することが少なくなって欲しいです。
## Boostnoteがデータを保存する仕組み
Boostnoteは、デフォルトでは`~/Boostnote`にフォルダやノートの情報を保存します。ですが、任意のディレクトリを保存対象に設定することも可能です。そして、この任意のディレクトリというのはBoostnoteのlocalStorageに記録されています。
DropboxやGoogleDriveを使って複数デバイス間でのノートの同期をさせているユーザーはこの任意のディレクトリを保存対象にする機能を使用している人も多いのではないでしょうか。
冒頭で述べた『一部のユーザー』とはこの機能を使用しているユーザーのことで、特に設定を行わずデフォルトのディレクトリにノートを保存しているユーザーには、このバグは発生していないはずです。

## ElectronのlocalStorageの場所
このバグが発生した原因にはElectronがlocalStorageを保存する場所に深く関係があります。Electronで作られたアプリケーションはそのlocalStorageを`~/Library/Application Support/**APP_NAME**/Local Storage`に保存します。そして、この`**APP_NAME**`は、アプリケーションの`package.json`の`name`や`productName`に依存します。
そろそろ気づいてきたかもしれませんが、v0.8.15の[アップデートに含まれるコミットにBoostnoteの`package.json`に`productName`を追加するもの](https://github.com/sferra/Boostnote/commit/a9acde07d1a1be8d5dad29e3682a562f615ebf06)がありました。それまでは`name: boost`に依存した`~/Library/Application Support/boost/Local Storage`にlocalStorageを保存していましたが、このコミットによりlocalStorageを`~/Library/Application Support/Boostnote/Local Storage`から参照するようになりました。
※ここで出てくるパスはMacOSでのものです

## つまり、原因
つまり、localStorageを保存しているディレクトリの場所が変わったため、localStorageに保存していた情報が参照できなくなったのが原因です。BoostnoteではlocalStorageに、ノートの保存場所の他にUI等のカスタマイズ設定を保存していたため、このアップデートによってデータが消えなかったユーザーも設定が全て飛ぶバグには見舞われたと思います。（僕もその一人）
このバグは致命的なもので、ユーザー的にもメンテナー的にもとても困惑して、しばらく調べて原因を探して、やっとわかったので、モヤモヤしていたユーザーや、他のElectronアプリ開発者様へのTipsとして記事にさせてもらいました。

## 参考にした記事
* https://qiita.com/khsk/items/90486b2359aa6f9d4b94
* https://github.com/electron/electron/blob/2af7c37d13cfeabbcf548f063e83321cb39b850f/docs/api/app.md#appgetpathname
for文中でreturnしてはならない


~~for文の中にreturnを書くと、1回しか回らない。~~
~~下のサンプルコードの~~
~~for (; ;)~~
~~は無限ループのはずだが、~~
~~returnでループが打ち切られて即終了となる。~~

~~まともなコードを書くのであれば、~~
~~returnはforの外に書く必要がある。~~

```java
public class ForReturn {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		String result = forReturn(2);
		System.out.println(result);
	}

	public static String forReturn(int i){
		for (; ;){
		return "不合格";
		}
	}
}
```

```:実行結果
不合格
```

~~ということを今更になって学んだ今日でした。。。。。~~
メモ：brakemanが文字コード関連でうまく動かない

この記事は
===

* 単なるメモです

困った事
===

* 超適当に作ったdockerコンテナの中でbrakeman実行しようとしたらエラーが発生してうまく動かない

```
Error: invalid byte sequence in US-ASCII While processing /var/rails....
```

対応
===

* これまた超適当に環境変数指定して実行して回避

```
RUBYOPT=-EUTF-8 brakeman
```

終わりに
===

* 動けばいいんですよ
Git コミット間の差分ファイルを抽出してコピー

# コマンド

## 変更後を取り出し

```
DIR=mod; mkdir -p $DIR; \
git diff HEAD^ HEAD --name-only --diff-filter=MA | xargs -i cp --parents ./{} ./$DIR
```

やってること：
変更後の格納用ディレクトリを作る→差分ファイルパス一覧をxargsからcpに渡す→作成したディレクトリにコピー

## 変更前を取り出し

```
DIR=org; mkdir -p $DIR; \
git diff HEAD^ HEAD --name-only --diff-filter=MA > change.txt; \
git checkout HEAD^; cat change.txt | xargs -i cp --parents ./{} ./$DIR; \
git checkout master
```

master以外のブランチならmasterのところを作業中のブランチ名に置き換える

やってること：
変更前の格納用ディレクトリを作る→差分ファイルパス一覧をchange.txtに出力→ワーキングツリーを変更前の状態に戻す→change.txtの内容をxargsからcpに渡す→作成したディレクトリにコピー

# なんでこんなことしたいの？

差分ファイルを手動でファイルサーバーに格納することを求められるから…
本番環境の不要なコードをすべて削除したら49.6%のコードダイエットができたはなし

- Meguro.rb #8 のLT資料です

---

# 自己紹介 :sunglasses: 
![サンチェくん130x148x.png](https://qiita-image-store.s3.amazonaws.com/0/118590/e25053ae-08a8-b098-3db0-705fe49e9dd6.png)

- GitHub: [tackeyy](https://github.com/tackeyy)
- Twitter: [3cche](https://twitter.com/3chhe)
- Blog: http://tackeyy.com/

---

# 今日お話する内容 :muscle: 

1. きっかけ
2. 未使用のコードを発見するための仕込み :ramen: 
3. コードの削除 & デプロイ
4. はまったところ
5. まとめ

---

# きっかけ :airplane_departure: 

[![Screenshot from Gyazo](https://gyazo.com/51c42b87157487ce3756f4bc96104440/raw)](https://gyazo.com/51c42b87157487ce3756f4bc96104440)

refs: [muramurasan](https://twitter.com/muramurasan)さんの[Railsで効率的かつ安全に未使用のメソッドを削除した](http://texta.pixta.jp/entry/2017/05/25/123845) 

---

要約すると・・・

- Rubyは動的にメソッドを呼び出せるので静的解析・動的監視で未使用コードを炙りださないといけない
- 静的解析 + 実際にメソッドが呼ばれているかのロギングを自分でやるのはだるいし本番のコードを汚染する
- そこで [okuribito_rails](https://github.com/muramurasan/okuribito_rails) を使おう！

---

# 未使用のコードを発見するための仕込み :ramen:

## 静的解析

- [debride](https://github.com/seattlerb/debride)
- 未使用の可能性のあるメソッドを抽出してくれる

## 動的監視
- [okuribito_rails](https://github.com/muramurasan/okuribito_rails)
- 監視対象のメソッドを定義したymlをおいておくとmethod callの度にカウントしてくれる

---

# コードの削除 & デプロイ :muscle: 

1ヶ月ちょっと寝かせた後に動的監視でも呼ばれていないメソッドを削除していった結果・・・

---

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">最終的に49.6%で終わり。<br>（´-`）.｡oO（不要なコードありすぎてわろた</p>&mdash; 3chhe (@3chhe) <a href="https://twitter.com/3chhe/status/888589528180576256?ref_src=twsrc%5Etfw">2017年7月22日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

---

[![Screenshot from Gyazo](https://gyazo.com/f5f271404216aeb1b673ccc2acb26ecf/raw)](https://gyazo.com/f5f271404216aeb1b673ccc2acb26ecf)

---

# はまったことろ :alien: 

- インデックス名がながくてokuribito_railsのmigrationがこける
    - okuribito_railsのWebUIに速度をもとめないのでいったんインデックスを削除して対応
- okueibiro_railsを入れてからきちんとテストしないエラーになるケースがある
    - 自分のリポジトリにフォークしてきてコードを修正 or ymlを整理

---

# まとめ :sushi: 

- okuribito_rails便利
Qiitaで技術ブログを始めようと思った理由

こんにちは。

最近、本格的にプログラミングの勉強を始めたので技術ブログでも書いてアウトプットしていきたいな～と思っていたら「はてなブログかQiitaが良い」という記事を見つけたので、いろいろ比べてQiitaで投稿していこうと思いアカウントを開設しました。

自分の性格的に好奇心旺盛でいろんな技術に興味は持つものの、アウトプットする場所をどうしようかなと悩んでいたのですがブログとして書くことで言語化する能力もあがるとなると一石二鳥だなと思い、アウトプットしようと決意しました。
<h1>アウトプットするとよって得られるもの</h1>
アウトプットすると良いというのは、いろいろな所で言われています。
いろいろな所で言われていますが自分なりにまとめると

<ol>
<li>言語化しないといけないので、分からない所が浮き彫りになる</li>
<li>逆に自分が何を理解しているのか分かる</li>
<li>書くことによってさらに理解が深まる</li>
<li>言語化する能力が上がる</li>
<li>ポートフォリオになる</li>
</ol>


ことですね。
いいことしかありません。デメリットはないと思います。
僕の中では、インプットよりアウトプットの方を多くしていきたいと思っているのでQiitaに投稿することはピッタリの選択でした。

5番目のポートフォリオに関しては、GitHubのソースコード以外にも技術ブログを評価してくれる会社も増えてきたので嬉しい傾向ですね。

<h2>これから</h2>
学んできたことを全部ここに書くつもりでやっていけたらな〜と思っています。プログラミングを初めたばっかりの頃は正直、挫折しそうになったことはたくさんありますが知識増えれば増えるほど楽しくなってきてると実感しているので、このまま突っ走って頑張っていこうと思います！
Gitでignoreされてるか確認する

`.gitignore`書いてみたけど「本当にignoreされるのかわからない！」と悩むケースがあったんで、メモ書き程度に。[（翻訳）【GitHub公式】Gitコマンドチートシート](https://qiita.com/okamu_/items/d52a6900311ad9073628)をみて、「あーなるほどな！」と思って書きました。

# 開発環境
+ Mac
+ iTerm2
+ zsh

# .gitignoreを書いてみる

以下のようなディレクトリにいる状況で、`.gitignore`に`hoge`という拡張子のファイルをすべて無視するように記述します

```shell-session
$ tree

├── test.hoge
├── test.text
└── dir
    ├── test2.hoge
    └── test2.text
```

```
--- #.gitignore ---

*.hoge
```

しかし`git add`する前に`git status`をしても`dir`の中がどうなっているのかわかりません
（addした後なら当然わかりますから、とりあえず`git add`するのは１つの手）

```shell-session
$ git status

Untracked files:
	.gitignore
	test.text
	dir/
```


# ignoreされてるか確認
### `git status --ignored`
これでいけるらしい...... が`git add`する前では、`dir`のなかの`test2.hoge`が`Ignored files`として表示されない
（`git add`した後ならきちんと表示される）

```shell-session
$ git status --ignored

Untracked files:
	.gitignore
	test.text
	dir/

Ignored files:
	test.hoge
```
### `git ls-files --other --ignored --exclude-standard`
そこで使うのが`git ls-files --other --ignored --exclude-standard`です
`git add`の前でもどのファイルが無視されているのかがわかります

```shell-session
$ git ls-files --other --ignored --exclude-standard

test.hoge
dir/test2.hoge
```

きちんと`*.hoge`が無視されているのが確認できました！

# 参考

+ [（翻訳）【GitHub公式】Gitコマンドチートシート](https://qiita.com/okamu_/items/d52a6900311ad9073628)
+ [github-git-cheat-sheet](https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf)
python2でi18n.lazy_gettext省略記法が使えないerror

## _('hogehoge')でTypeErrorが出た

GAE/pythonで国際化対応のためi18nを入れようとしたのだが動かなかった。
GAEはpython2なのである。。。。。という問題

```python
from webapp2_extras.i18n import lazy_gettext as _

i18n.get_i18n().set_locale('en_US')
message = _("hogehoge")
```

さて、これを動かしたところ、

```
TypeError: 'list' object is not callable
```

リスト??

文字列がリスト評価されてしまっている可能性も考えて

```python
message = _("a")
```

としたが、変わらず、

```python
print type(_)
```

返ってきた型はこれ

```
<type 'list'>
```

そういえば、コードの中で、_にリスト代入していたかもしれない

```python
_abc = [i for i, _ in enumerate(abc)]
```

みたいな。

### python2

```
Python 2.7.10
>>> abc = ["a", "b", "c"]
>>> _abc = [i for i, _ in enumerate(abc)]
>>> type(_)
<type 'str'>
```

### python3
```
Python 3.6.2
>>> abc = ["a", "b", "c"]
>>> _abc = [i for i, _ in enumerate(abc)]
>>> type(_)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
```

なるほど。


#　結論
* _にリスト入れるのがよくないね
* 名前空間汚してしまったのが問題でした。_に入れるのはやめよう！！
長すぎるパラメータ付きURLを短くする方法 

##今回はパラメータ付きURLの短縮方法をご紹介します。

カスタムキャンペーンのパラメータを含むURLは非常に長い物となります。
問題点としては、見た目の悪さや折り返されてURLが途切れ、リンクが正しく動作しなくなるといったことが挙げられます。

この問題の解決には短縮URLの利用が欠かせません。
短縮URLのサービスには様々なものがありますが、今回はその内の1つである[Google URL Shortener](https://goo.gl/)を紹介します。

使い方はシンプルです。
パラメータ付きのURLを入力後、Shorten URLボタンをクリックすると短縮したURLが生成されます。

また、[Google URL Shortener] (https://goo.gl/)で短縮したURLに有効期限はありません。
新卒エンジニアがエンジニアのカテゴリーを5つに分けてみた

移動時間にぼーっとQiitaを眺めていたらこんな記事を見つけました。

ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】
→https://qiita.com/jacksuzuki/items/b2fa6b44962e73a53d08

ロシアの天才ハッカーが、エンジニアの担当分野5つをそれぞれ詳しく説明してくれている記事です。

新卒エンジニアの僕にはとても興味深い内容だったので、この記事を元にそれぞれの分野のキャリアをまとめます。

#Application Engineer
webサービスやスマホアプリを開発するのが、この分野のエンジニアです。
具体的な言語には、PHPやRubyなどがあります。

主なキャリアは2つあると思っています。
##1.ビジネスサイドに行くパターン
「自分で作ったサービスが人に使われるのを見たい」
「ビジネスサイドにも興味ある」
という方には最適な分野ではないでしょうか。

将来的にはディレクターやプロデューサーなどの職種につくことも可能だと思います。

僕はビジネスサイドもやりたいと思っているので、
今のところアプリケーションエンジニアとしてキャリアを進めていこうと思っています。

##2.言語のスペシャリストになるパターン
文字通り使っている言語を極めるキャリアです。
その言語の需要があればあるほど良いですね。
なので、どの言語が今後流行るか見極める力は必要です。

#Infrastructure Engineer
インフラエンジニアですね。
Amazonが運営するAmazon Web service(AWS)などを触る人になります。

クラウドが発達したので、どの分野のエンジニアでもインフラを触りやすくなりました。
けど、より深く触ろうと思ったらこの分野を深く学習する必要がありますよね。

この分野を深く学習するとどのようなキャリアになるのかは、僕もまだよく分かっていません笑(すいません、、、)
なので、情報が集まりしだい記事を更新したいと思います。

#Database Administrator
データを扱うエンジニアです。定番の言語はSQLでしょう。

データを用いた機械学習、AIなどが流行っているので需要はあるのかなーと。
そして、データベースを触れるだけでなく、データの分析もできると良さそうです。
例えば、SQLかつPythonを触れるとかは親和性がありますよね。

個人的には、数字を見るのとか好きなのでデータベースの学習もしたいですね。

#Security Engineer
セキュリティのエンジニア。
ドラマでよく出てくるハッカーは、この分野の人になります。

今話題のブロックチェーンの技術も、セキュリティの一種なのか？
と勝手に考えています。

特にこの分野は、技術的に上には上がいるので何かで差別化する必要があると思います。

#Technical Program Manager
エンジニアを束ねるマネージャーですね。
プロダクトとエンジニアのマネジメントを出来る必要があります。

技術力に加えて、コミュニケーション能力も求められます。
会社のCTOになりたい人は、この分野で戦うべきでしょう。

#自分がどの分野が好きなのか、得意なのか考えよう
5つの分野について考えました。
どの分野が好きなのか、また得意なのかを考えて戦う場所を選ぶ必要がありそうです。

常に長期的な目線で、普段の学習に励もうと思います。
ではでは！
conemu

# babun commands

> -new_console:d:C:\初期DIR  %userprofile%\.babun\cygwin\bin\mintty.exe /bin/env CHERE_INVOKING=1 /bin/bash.exe

# putty commands

> -cur_console:t:"vm" "C:\Program Files\PuTTY\putty.exe" -load "default settings"

# font

> [Ricty Diminished](https://qiita.com/murachi1208/items/513ffa243a879ee250f2)

# setting

> [tab&starting](http://yanor.net/wiki/?Windows-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%2FConEmu%2F%E3%82%BF%E3%82%B9%E3%82%AF%E3%83%BB%E8%B5%B7%E5%8B%95%E8%A8%AD%E5%AE%9A)

# When I run git status in git shell and in Babun I get different results.
It is probably an end-of-line issue. Execute git config --list both in cmd and in Babun and compare the core.autocrlf values. If your cmd prints core.autocrlf = true execute git config --global core.autocrlf true in Babun.
> [faq list](http://babun.github.io/faq.html)

# copy&paste

> [question solution](https://github.com/babun/babun/issues/97)