OmniAICreator/Qiita-1.07M huggingface dataset:
Rustで自然変換する話

# はじめに

さて前回まで、関数型言語を使うプログラマーにとって「ある構成がただの関数ではなく、実は本質的には自然変換である」ケースに気づけることが、関数型言語をより良く使いこなす上で重要になってくるのだという話をしてきました。

えっ、してない？

今日は13日の金曜日だ…奇跡がおきても不思議じゃない…

そんな話です。よろしくお願いいたします。よろしくお願いいたしました。

# 関手と自然変換

## 関手 is 何？

まず `Vec` や `Option` など、ある種のものが「関手」と呼ばれるものであると考えられることから見ていきましょう。まずこれらは一旦「型 `T` を受け取って、新しい型 `Vec<T>` を返す」関数と考えます。

このとき `Vec` が「型 `S` から 型 `T` への矢印」を「型 `Vec<S>` から型 `Vec<T>` への矢印」に変換する働きを持っている場合、こいつが関手であると雑に考えることにしましょう。矢印というのはお察しの通り、この場合はただの関数です。

```rust
let a: Vec<String> = vec![1,2,3,4,5].iter().map(|i| i.to_string()).collect();
```

`to_string` という「`i32` から `String` への矢印」が、全体として「`Vec<i32>` から `Vec<String>` への矢印」に「変わっている」ことに注意しましょう。`Option` も大体同じです。

## 自然変換

以下のような「関数」を考えてみます。

```rust
fn vec_to_option_nt<T: Clone>(src: &Vec<T>) -> Option<T> {
  src.get(0).map(|x| x.clone())
}
```

`Vec` の先頭要素をあれば返す（なければ `None`）だけの簡単な関数です。

```rust
fn main() {
  let a = vec_to_option_nt(&vec![1, 2, 3, 4, 5]);
  println!("{}", a.map(|i| i.to_string()).unwrap_or("None".to_string()));

  let a = vec_to_option_nt(&vec!["red", "blue", "green", "yellow", "purple", "red-no-ikiwakareta-ani-gold"]);
  println!("{}", a.map(|i| i.to_string()).unwrap_or("None".to_string()));

  let a = vec_to_option_nt(&(vec![] as Vec<f32>));
  println!("{}", a.map(|i| i.to_string()).unwrap_or("None".to_string()));
}
```

この関数は型パラメータ `T` を通じて

* `Vec<i32> -> Option<i32>`
* `Vec<char> -> Option<char>`
* `Vec<bool> -> Option<bool>`
* `Vec<String> -> Option<String>`

...

* `Vec<OregaKangaetaSaikyouNoStruct> -> Option<OregaKangaetaSaikyouNoStruct>`

への変換を**全部同時**に引き起こしていることがわかります。つまり「関手 `Vec` を関手 `Option`」に変換していると考えて良いということになります。これが自然変換です。

何だただのジェネリックな関数か...と思われるかもしれません。たしかに一面ではそうですが、「自然変換」であるためには単にジェネリックであるだけでは足りません。

自然変換は、任意の「型 `S` から 型 `T` への矢印」（つまり関数）と交換可能であるという性質を持っています。（今回は雑に考えているので、任意と書きましたが、上記の実装では `Clone` なものに限られます。）

意味がわかりませんね。わからないので、以下のコードを見てみましょう。

```rust
use std::time::Instant;

fn vec_to_option_nt<T: Clone>(src: &Vec<T>) -> Option<T> {
  src.get(0).map(|x| x.clone())
}

fn main() {
  let target = (0..10000000).collect::<Vec<i32>>();
  let int_to_bool_fn = |i: i32| -> bool { i % 2 == 0 };

  let time = Instant::now();
  let result1 = vec_to_option_nt(&target).map(int_to_bool_fn);
  println!("{}", time.elapsed().as_millis());

  let time = Instant::now();
  let result2 = vec_to_option_nt(&target.clone().into_iter().map(int_to_bool_fn).collect());
  println!("{}", time.elapsed().as_millis());

  assert_eq!(result1, result2);
}
```

`vec_to_option_nt` をしてから `int_to_bool_fn` をしても、`int_to_bool_fn` をしてから `vec_to_option_nt` をしても結果が変わっていないことがわかると思います。

結果が同じなので、多分実装はどちらでも良いんじゃないかなと思います。多分ですが。

この性質は「関数がジェネリックに書ける」ことだけではどう頑張っても導出されないので、「自然変換になっているか」はプログラマーが明確に意識する必要がありそうです。

また、ある構成が本質的には自然変換であることに気づけば、既存の自然変換を「合成」することで（普通の意味で）自然で、スマートな実装が得られるかもしれません。もちろんこの場合、ジェネリックなのはおまけでしかなく、自然変換であること is 本質。

さらに「これ…関数というよりは、本質的には自然変換じゃないですかねぇ…(ﾄﾞﾔｧ)」とドヤ顔できますね。

# おわりに

いかがでしたか？

関数型言語を使うプログラマーにとって「ある構成がただの関数ではなく、実は本質的には自然変換である」ケースに気づけることが、関数型言語をより良く使いこなす上で重要になってくるのだという話をしてきました。

もともと Scala で書いていたのですが Rust で書き直してみたところ、とても大変なことになりました。

「Rustは学習コストが高い」そう考えている人も多いかと思います。ですが、そういった人たちにも「やっぱりRustは学習コストが高い」ということが伝われば幸いです。
全ての監視は"Cloud Watch"にお任せ

#自動監視サービス"CloudWatch"
こんにちは．

最近はECサイトを作っています．
そこで，AWSの"CloudWatch"がかなりコスト削減に繋がったので，
今回は紹介します．

結論から言うと，
"管理者ページ作る必要なくなる"
"めんどうなイベントコード必要なくなる"
このくらいのことならcloudWatchで出来てしまいます．

それではまとめていきましょう．

##CloudWatchのお仕事
- メトリクス（分析に必要なデータ）の収集
- ログの収集
- モニタリング
- アラーム設定

主にこれらが仕事です．
EC2やDBを監視して，ダッシュボードにグラフで表示出来てしまいます．

##CloudWatchの構成
まず，CloudWatchは，
CloudWatch/CloudWatch logs/CloudWatch events
という3つサービスで構成されています

###CloudWatch
メトリクスの収集，サービスの監視をしてくれます．

###CloudWatch logs
EC2インスタンス上のos/appログを取得してくれます

###CloudWatch events
リソースの変更をトリガーとしてアクションを実行
SNSと連携もできる
aws用語のSNSはサーバーノーティフィケーションサービスです
ソーシャルネットワークサービスじゃないよ
SNSに登録して通知を飛ばすイメージ

実行するアクションをLambda関数で指定できます．

##EC2監視
CPUを知りたい場合には，**CloudWatchエージェント**をインストールすると
自由に定義するカスタムメトリクスに収集出来ます．
わかりやすく言うと，
メモリ，ネットワークの詳細，プロセスの詳細を知りたい人用です．

また，デフォでEC2の監視は5分間隔．
課金すれば3分，1分，秒数間隔でモニタリングできる．

でも，その分保存期間も短くなります．
1秒監視とかすると，収集データで溢れかえるからね．

60秒未満 -> 3時間
1分    -> 15日
5分    -> 63日
1時間  -> 455日


#ついでにCloudTrailも理解しちゃおう
CloudWatchとCloudTrailは連携出来るから，
CloudTrailをまず紹介．
##CloudTrailとは
AWSに対するアクティビティログ
（誰がいつAWSマネジメントコンソールにログインしたか）
を記録しています．(グローバルもリージョンもごとも可能)
ちなみに
90日分のデータを持っていますが，
**証跡**を有効化すると，S3に保存してくれます．
これで長期間のログを保存できるっていう．

まあ，何が言いたいかって言うと，
CloudWatchでIAMユーザーの監視もCloud Trailを知ってれば出来ちゃうよ．
全部監視出来るねCloud Watch!ってこと

連携手順は，
Cloud Trailでアクティビティ監視，記録
そのログを
CloudWatch　Logsに送信

監視サービスは他にもありますが，とりあえずここまで
Jupyter Notebookでconda仮想環境を使ってみる

#この記事は
今日は、 ```Jupyter Notebook```でconda仮想環境を使ってみたいと思います。
```Google Colaboratory```へ持ち出せないdatasetを扱うときに重宝しますね。

#前提
- ```Anaconda``` のインストールは終わっている
- ```Jupyter Notebook``` のインストールは終わっている
- 既存のconda仮想環境を作ってある (```<env_name>```という名前とします)

#準備
- Jupyter Notebookのプラグイン ```environment_kernels``` をインストールします。

```bash
pip install environment_kernels
```

今回は、conda仮想環境のデフォルトである```base```へインストールしています。
理由は、```Win + "r"``` -> ```"Jupyter Notebook"``` という操作で開きたいからです！

#仮想環境のコピー
既存の仮想環境をJupyter Notebookで使いたい。
しかし、その環境へJupyter Notebookをインストールする必要があります。

できれば既存はそのままにしておきたいので、ここでは

- 仮想環境をクローンすることにします。

```bash
# <env_name>は既存のconda仮想環境
# <new_env_name>は新しい仮想環境の名前を付けてください
conda create -n <new_env_name> --clone <env_name>
```

#Jupyter Notebookをクローン仮想環境へインストール

Jupyter Notebookのプラグイン ```environment_kernels``` が認識してくれるように、Jupyter Notebookを仮想環境へインストールします。

- クローンした仮想環境へ切り換えておきます。

```bash
conda activate <new_env_name>
```

- Jupyter Notebookをインストールします。

```bash
pip install jupyter
```

#Jupyter Notebookのconfig

- 設定ファイルを生成します

```bash
jupyter notebook --generate-config
```

- 設定ファイルを編集します
  - 手元がWindowsなので、notepadで編集しちゃいます 
  - 下記の \<user_name\> はあなたの環境にあわせて変更してください

```
notepad C:\Users\<user_name>\.jupyter\jupyter_notebook_config.py
```

- 開いたファイルの末尾へ下記の2行を追記してください
  - Anacondaのインストールのしかたによっては、下記例のようなパスになっていない場合もあります。適宜変更してください。
  - Pythonのパス指定は、区切り文字を"\"を"\\\"にするとか、"/"にするとか、r"～"にするとか、いろいろなやり方があります。<font color = "red">下記はwindowのパス文字列の"\"を"/"にしています。</font>

```
c.NotebookApp.kernel_spec_manager_class='environment_kernels.EnvironmentKernelSpecManager'
c.EnvironmentKernelSpecManager.env_dirs=['C:/Users/<user_name>/.conda/envs/']

# 下記の1行書きは2019-12-13現在ではうまくいきませんでした
# c.EnvironmentKernelSpecManager.conda_env_dirs = ['C:/Users/0000112345/.conda/envs/']

```

- 編集したら、保存して閉じます

#Jupyter Notebookで確認
- Jupyter Notebookを起動する
- "Kernel" -> "Change kernel"で環境を切り換えられていることを確認

![jupyter_notebook_condaenv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56003/cba65af8-0726-8dc8-f0af-f2ebddcd1afa.png)

#うまくいかなかったこと
- プラグインに認識してもらうには、ターゲット側にも Jupyter Notebook が必要ということを見落としていた。

#今後
Google Colaboratoryと同じ見た目にしたいな。どうすればいいんじゃろ？？

#参考
- [Automatic Environment Kernel Detection for Jupyter](https://github.com/Cadair/jupyter_environment_kernels)
MavenをWindowsにインストールする

## 手順

1. [公式ページ](http://maven.apache.org/download.cgi) から、最新版のBinary zip archiveをダウンロードして、任意の場所に解凍する
1. 必要に応じて、環境変数を編集
1. "mvn --version"でバージョン確認
1. 必要な場合は"conf\settings.xml"にプロキシ情報を設定

### 環境変数

| 環境変数名        | 説明              |
|:-----------------|:------------------|
| JAVA_HOME        | JDKのインストールディレクトリ |
| PATH             | Mavenのbinフォルダへのパスを追加<br/>例：set PATH="c:\program files\apache-maven-3.6.3\bin";%PATH% |

### "mvn --version"の実行例

```shell:
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: D:\Users\xxxxxxxx...
Java version: 11.0.3, vendor: Amazon.com Inc., runtime: C:\Program Files\Java\jdk11.0.3_7
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "windows"
```
### プロキシ設定

```xml:conf\settings.xml
<proxy>
  <id>optional</id>
  <active>true</active>
  <protocol>http</protocol>
  <username>ユーザー名</username>
  <password>パスワード</password>
  <host>ホスト名</host>
  <port>ポート番号</port>
  <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
```
Homebrewの更新でPipenv環境が壊れたときの対処

例えば以下のようなエラーが出たとき

```shell
$ pipenv run ./manage.py shell
Loading .env environment variables…
dyld: Library not loaded: @executable_path/../.Python
  Referenced from: /Users/zenwerk/.virtualenvs/some-project/bin/python
  Reason: image not found
/bin/sh: line 1: 10581 Abort trap: 6           pipenv run ./manage.py shell
make: *** [shell] Error 134
```

`Pipfile`があるディレクトリで、以下の手順で環境を作り直す

```shell
# 問答無用で既存の環境を消す
$ PIPENV_IGNORE_VIRTUALENVS=1 pipenv --rm

# pipenv 環境を作り直す
$ pipenv sync
Creating a virtualenv for this project…
Pipfile: /Users/zenwerk/ｓｒｃ/some-project/Pipfile
Using /usr/local/Cellar/pipenv/2018.11.26_2/libexec/bin/python3.7 (3.7.5) to create virtualenv…
⠏ Creating virtual environment...Already using interpreter /usr/local/Cellar/pipenv/2018.11.26_2/libexec/bin/python3.7

# 依存関係の再インストール
$ pipenv install --dev
```
Ubuntu 18.04 に Python3.7を入れる

# 理由とか

- Ubuntu 18 .04 は Python 3.6.9が入ってた
- デプロイしたら一部のTypeHintやら、dataclassでエラーに
- 標準のaptに3.7がいるので、入れてalternativesという王道
- 複数端末使う予定なので、Ansibleで出来るか確認したら追記するかも

# コマンド

``` bash
sudo apt install python3.7 -y

sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2

sudo update-alternatives --config python3
```

# 確認

`python3 -V`すると、`3.7.5`が帰ってくるはず。
さ、またwheel作らなきゃ……
ローカルPCのNode.jsでaws-sdkの認証を通す

## はじめに

ローカルPCでAWSの色々なサービスを操作するツールを作りたいときに、
認証が通せず苦労しましたが、この方法で通せるようです。

ファイルなんか作らずにメモリ内に閉じたかったのですが、無理そうでした。

## 認証を通すコード

``` dynamo-utility.ts
import AWS = require('aws-sdk');
import Fs = require('fs');

export class DynamoUtility {
  dynamoDb: AWS.DynamoDB;
  documentClient: AWS.DynamoDB.DocumentClient;

  constructor(credential: any) {
    const tmpFile = './credential.json';
    // 認証ファイルを生成
    Fs.writeFileSync(tmpFile, JSON.stringify(credential));
    // 生成したファイルを読み込ませる
    AWS.config.loadFromPath(tmpFile);
    // ファイル削除
    Fs.unlinkSync(tmpFile);
    // クライアント生成
    this.documentClient = new AWS.DynamoDB.DocumentClient();
    this.dynamoDb = new AWS.DynamoDB();
  }
}
```

``` environment.ts
// ...
    credential: {
      accessKeyId: 'xxxxxxxxxxxxxxxxxxxx',
      secretAccessKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
      region: 'ap-northeast-1'
    },
// ...
```

## さいごに

役に立ちましたら、記事にいいねをお願いします。
Section / Article / Figureタグについて


## Section タグ :dividers:

セクション（章や節）を表す。

```index.html
<section>
  <h1>見出し</h1>
  <p>本文</p>
</section>
```

**・ 見出しが必ずあること**
見出しが無い =　章や節ではない = **sectionではない**

・ 章や節の区切りやまとまりなどに使用
・ 意味や機能のまとまり
・ div と違い、文脈的な意味があるコンテンツに対し使用する。 よってsection 内には見出しが必須
・ 文章の論理構造用タグ
・ article同様、基本的にレイアウトのためには使わない
・ articleを内包可
・ **無理して使わなくてもよい**
・コンテナーとして使うならdivを使用


## Article タグ :page_with_curl:

ページのメインコンテンツを表す要素

```index.html
<article>
    <h1>Title</h1>
    <section>
        <h2>Section title</h2>
        <p>Content</p>
    </section>
    <section>
        <h2>Section title</h2>
        <p>Content</p>
    </section>
    <section>
        <h2>Section title</h2>
        <p>Content</p>
    </section>
</article>
```
・ ブログの投稿や記事１件、コメント１件分など独立して成立するコンテンツに使用
・article は section 同様、文脈的な意味がある コンテンツに対し使用
・内側の article が、外側の article の内容と関係がある場合、article を内包（ネスト）することができます。またsectionも内包できる。
・**レイアウトのために基本的はdivを使用使わない**
・無理して使わなくてもよい


## Figureタグ :frame_photo:

画像などのまとまりを表す時に使用します。
具体的にはコンテンツに挿入する画像（写真）や、表、ソースコードなどを囲む。

```index.html
<figure>
  <figcaption>
    注釈（説明文）
  </figcaption>
  <img src="" alt=""> //画像
</figure>
```

`divタグ`でも良いが、`figureタグ`で囲むことによって画像があることが判断しやすい。
またfigure要素は**自己完結したもので、ドキュメントのメインのフローから単独のユニットとして参照されるもの**である必要がある。つまり、その部分を文書から切り出したとしても元の文書に影響がないとともに、切り出した内容自体で意味が通るようにする必要があります。また、figcaption要素によってキャプションを付与できます。
VBScriptでブラウザ自動操作

やりたかったこと
・ブラウザの手入力が面倒なので、自動操作出来るようにしたい

課題
・今の現場（Web開発）が「OS:Windows」「ツールのダウンロードには毎回許可がいる」「閲覧できるサイトとできないサイトがある」といった制限がある。

やったこと
[VBScriptで作ってみました](https://github.com/LoveHeineken/vbscripts/blob/master/)。また、長文をScriptファイルに直書きするのが嫌だったので、テキストファイルからも読み込むようにしました。

ブラウザ自動操作（IE限定）

```vb:AutoTypingBrowser.vbs
Dim url: url = "https://www.foobar" 
Dim ie 
Set ie = CreateObject("InternetExplorer.Application") 
ie.navigate2(url) 
ie.Visible = True 
ie.document.getElementById("foo").value = "hoge" 
```

同じ階層にある全てのテキストファイル読み込み

```vb:FileReader.vbs
Dim objFSO
Dim objFile
Dim objPath
Set objPath = CreateObject("Scripting.FileSystemObject").GetFolder(".") 
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
For Each objFile In objPath.Files
    Dim FileName
    FileName = objFile.Name
    If InStr(FileName, ".txt") > 0 Then
        Set objFile = objFSO.OpenTextFile(FileName)
        Dim textContent: textContent=""
        Do While objFile.AtEndOfStream <> True
            fileContent = fileContent + objFile.ReadLine & vbCrLf
        Loop
        objFile.Close
    END IF
NEXT
WScript.Quit(100)
```

結論
次回はJavaScriptで作ります
コンポジション関係にあるコンポーネント間の操作

## はじめに

Angularの2つのコンポーネントがコンポジション関係にあるときの操作についてです。
所有側コンポーネントをOwnerComponent、部品側コンポーネントをPartComponentとして記載します。

## 所有側から部品側へのデータの受け渡し

``` owner-component.html
<app-owner>
  <!-- 部品側のプロパティと所有者側のプロパティを関連づける -->
  <!-- リアルタイムに値が同期する -->
  <app-part [partProperty]="ownerProperty"></app-part>
</app-ower>
```

``` owner-component.ts
export class OwnerComponent {
  ownerProperty: string;
}
```

``` part-component.ts
export class PartComponent {
  <!-- @Input()が必要 -->
  @Input() partProperty: string;
}
```

## 所有側から部品側へのfunction呼び出し

``` owner-component.html
<app-owner>
  <!-- #で任意の名前を付ける -->
  <app-part #part></app-part>
</app-owner>
```

``` owner-component.ts
export class OwnerComponent {
  // #で付けた名前をプロパティに関連づける
  @ViewChild('part') private partComponent: PartComponent;

  exampleFunction() {
    // 部品側への呼び出し
    this.partComponent.onReceiveEvent('foo');
  }
}
```

``` part-component.ts
export class PartComponent {
  onReceiveEvent(variable: string) {
    // ...
  }
}
```

## 部品側から所有側へのイベント通知

``` owner-component.html
<app-owner>
  <app-part (voted)="onVoted($event)"></app-part>
</app-owner>
```

``` owner-component.ts
export class OwnerComponent {
  onVoted(variable: string) {
  }
}
```

``` part-component.ts
export class PartComponent {
  @Output() voted = new EventEmitter<string>();

  vote() {
    const variable: string = '渡す値';
    this.voted.emit(variable);
  }
}
```

## さいごに

役に立ちましたら、いいねをお願いします。
WordPressでウィジェットインストール時にエラーになるときの対処法

<H2>問題</H2>
WordPressでウィジェットをインストーラしようとしたら、以下のエラーが出た。

```
failed to connect to ftp server 21
```

<H2>解決方法</H2>
1. WordPress直下のwp-config.phpを開き、以下を追加   
   ```define('FS_METHOD', 'direct');```

2. それでも解決しない場合は、/wp-content/plugins/の権限を```chmod 777 plugins```で変更。

<H2>参考ページ</H2>
https://www.digitalocean.com/community/questions/can-t-install-wordpress-themes-ftp-error
アプリ管理者がJavaScriptカスタマイズを行うためのプラグイン

# 

Qiitaに書くこと自体がひさしぶりになってしまいました。Spicaです！
[機能拡張スタンダードAll-In](https://spica.tokyo/bluelaunch)というプラグインを販売しております。

最近ハマっているゲームはペルソナ5ロイヤルです。無印のペルソナ5もやりましたが、また最初から遊んでもやっぱり面白いっすね。あと十三機兵防衛圏というのを積んでいます。P5Rの1週目が終わったらとりかかる！

関係ない話はこのへんにして……kintoneの話を。
今回は基本に立ち返って、アプリのJavaScriptカスタマイズを手軽にする方法について書いていこうと思います。
ネタとしては軽めかなと思いましたが、kintoneカスタマイズのハードルを少しだけ下げてみようという試み、ということで。
プラグインも作りましたのでお使いいただければと。

# そもそもカスタマイズするためには

[JavaScriptやCSSでkintone全体をカスタマイズする（kintoneヘルプ）](https://jp.cybozu.help/k/ja/admin/system_customization/javascript_fullcustomize.html)
にある通り、JavascriptやCSSファイルの読み込みを設定できるのは**システム管理者**のみとなっています。

セキュリティ的には仕方ない部分もあるんですが、この縛りさえなければ……！　と思ったことある方、多いんじゃないかなと思います。きっと多い。多いんじゃないかな。多いに決まってる。
ちゃんとアプリのアクセス権限を統制して編集者に気をつけるからアプリ管理者にもカスタマイズさせてくれよ、と。

# pluginの設定情報にスクリプトを保存したらいいのでは？

実装の仕組みですがしごく単純。
jQueryにglobalEvalというメソッドがあります。
渡された文字列をグローバルのスコープでスクリプトとして実行するというものです。
プラグインにスクリプトを保存して、こいつで実行してしまえというすんぽう。

CSSも編集できるようにしました。
こっちはもっと単純に、`<style>`タグの中身にして`body`あたりに要素を追加してやるだけです。

# というわけでplugin作りました
![icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/db48d69e-bc16-16ba-d5c0-f40b675ded88.png)
[プラグイン (CustomizeEditor)](http://spica.tokyo/dl.php?f=customize_editor)

プラグインの設定画面はこんな感じです。
![kintone_adc_2019_img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/0add0ad4-5739-b204-04b8-86654b9d33e8.png)

なんとなくエディターふうに体裁を整えてますが、ここで書いたスクリプトはevalで実行されるので、デバッグは非常に大変です。
ここはひとつ、[kintone開発者ライセンス](https://developer.cybozu.io/hc/ja/articles/200720464-kintone-%E9%96%8B%E7%99%BA%E8%80%85%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9-%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83-)を申請してですね、自分の環境でスクリプトを作り込んで完成したものをmasterデプロイする感覚で使うのがよきかなと思います。

みんな開発者になればいいんですよ。以上です！
正規表現からテストデータを作るツールを作った話

# 概要
「8桁の英数字,4桁の英数字」のような指定されたフォーマットに従って、テスト用のダミーデータを大量に作成したいケースはそれなりにあるかと思います。
今回そのためのオンラインツールを作ったのでその紹介と、開発中に得た知見について書きます。

# 技術要素
React+Redux+TypeScript+Material-UI+Firebaseで作っています。

# ツール
[Random String Generator](https://random-string.gnrt.app//)

指定フォーマットの正規表現を入力して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99106/ea2dbc83-ec85-2204-04a4-8b0f06992f70.png)

作る数を入れて、`GENERATE`ボタンを押すと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99106/71c9b87e-ae63-bd93-7db4-fcf388265f8d.png)

テストデータが生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99106/7ec521de-dc71-0f2c-c97c-f36fd8bab6ce.png)

生成されたデータはダウンロード、またはクリップボードへコピーできます。

作成できる数の上限は10,000件までに設定しています。

# 正規表現から文字列の生成
[randexp](https://www.npmjs.com/package/randexp)というライブラリを使って、正規表現からそれに沿ったランダムの文字列を生成しています。

基本的な正規表現は問題なく使えるようですが、
- `*`
- `+`
- `{3,}`

のような、生成できる文字列の長さに上限がないものは、上限１００としているようです。
なので、

```
a+
```
といった正規表現からは

```
# 最短
a
# 最長
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```

といった文字列が生成されます。

# previewの生成
正規表現を入力した後、1秒間更新が無ければ、入力欄下部にpreviewを出しています。
この処理はせっかくなのでHookを使って実装してみました。

useEffectと[useDebouce](https://www.npmjs.com/package/use-debounce)を使って、下記のようにして実装しています。

```js
const [debounceSourceText] = useDebounce(sourceText, 1000);
useEffect(() => {
  dispatch(actions.previewUpdate());
}, [debounceSourceText]);
```

`debounceSourceText`は1000ミリ秒間`sourceText`に更新がなかった場合に、最新の状態に更新されます。
`useEffect`は`debounceSourceText`が更新されたときのみに実行されるので、結果として正規表現の最終更新から1秒後にactionがdispatchされてpreviewが更新されることになります。

# まとめ
他にもmaterial-ui周りなどいくつか書きたいことがありますが、長くなるのでこの辺りで。
テストデータを作る必要があるときに利用してもらえるととても嬉しいです！
今更，GoでFizzBuzzしてから，3の付く世界でアホになる

# 前置き

これはNISE (南山大学 青山研究室) Advent Calendar 2019の13日目の記事です．

昨日は，後輩の[@RomuskaPaloUrLaputa](https://qiita.com/RomuskaPaloUrLaputa)がpythonのデータプロットについて書いてくれました．いや，まさかの解決策がすぐにコメントされるのはちょっと面白いｗ

今回は，結構今更感あるなーとか，既知感満載とかいうコメントを見なかったことにして，これから就活とかでコーディングテストがあるときの参考になればと思います．


# とりあえず，FizzBuzz書いて

こんな風に面接官に言われ，自分の後ろにあるホワイトボートに立たされたあなた．

言語はなんでもいいという

さて，どんな風に書きますか？？

## want to do 

- とりあえず，1~10000くらいまで
- 3の倍数ではFizz
- 5の倍数ではbuzz
- 15の倍数ではFizzBuzz


とまあ，わざわざ書かなくてもって感じですよねｗ

## 実装

Goで今回は実装しました．
そのコードは以下になります！

```FizzBuzz.go
package main

import (
	"fmt"
)

func main() {
	i := 1

	for i < 10001 {
		if i%15 == 0 {
			fmt.Println("FizzBuzz")
		} else if i%3 == 0 {
			fmt.Println("Fiz")
		} else if i%5 == 0 {
			fmt.Println("Buzz")
		} else {
			fmt.Println(i)
		}
		i++
	}

}
```

いや，こんなの誰だって，解けるわ！って普通に言われそうです．

実装結果は，こんな感じ

<img width="946" alt="スクリーンショット_2019_12_13_9_13.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123597/36824d0d-c8b6-54d5-129b-a46f9f646b86.jpeg">

では，ここからちょっと改良していきます

とりあえず，こちらが入力した数値までFizzbuzzしてよとする場合は．

```unlimitfizzbuzz.go
package main

import (
	"fmt"
)

func main() {

	fmt.Print("いつまでFizzBuzzをやらせるんだね!?: ")
	var input int
	fmt.Scanf("%d", &input)

	for i := 1; i <= input; i++ {
		fizzbuzz(i)
	}
}
func fizzbuzz(i int) {
	if i%15 == 0 {
		fmt.Println("FizzBuzz")
	} else if i%3 == 0 {
		fmt.Println("Fiz")
	} else if i%5 == 0 {
		fmt.Println("Buzz")
	} else {
		fmt.Println(i)
	}
}
```

はい，こんな感じ

実行結果もそんな変わらず，
<img width="640" alt="スクリーンショット_2019_12_13_9_34.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123597/f4ba6bb3-0357-9160-78ef-5448aa829e6b.jpeg">

こんな感じかな？

まあ，大したことをしていない

# んじゃあ，あの昔の芸人さんみたいに3の付く数字で，阿呆になってよ

と面接官が言ってきた

ちょっとジェネレーションギャップで，エン○の神様とか知らないとか，世界のナ○アツとか知らないとかいうことが考えられるので，
やりたいことを書いておく

## want to do

- とりあえず，1~10000くらいまで
- 3の倍数と3の付く数字で，アホになる

## 実装

あー，PHPはstrposとか，Pythonはfindとかでいいんですけど，Goではそれはないんで普通に関数を定義します．

```nabeatsu.go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	fmt.Print("いつまでFizzBuzzをやらせるんだね!?: ")
	var input int
	fmt.Scanf("%d", &input)

	for i := 1; i <= input; i++ {
		nabeatsu(i)
	}
}

func is_aho(i int) bool {
	var strInt = strconv.Itoa(i)
	for k := 0; k < len([]rune(strInt)); k++ {
		if '3' == strInt[k] {
			return true
		}
	}
	return false
}

func nabeatsu(i int) {
	sanbai := "3の倍数"
	santsuku := "3野付く数字"
	if is_aho(i) && i%3 == 0 {
		fmt.Println(i, sanbai+" "+santsuku)
	} else if is_aho(i) {
		fmt.Println(i, santsuku)
	} else if i%3 == 0 {
		fmt.Println(i, sanbai)
	} else {
		fmt.Println(i)
	}
}
```


出力したい言葉は各自で選んでください．

この出力結果は

<img width="676" alt="スクリーンショット_2019_12_13_13_26.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123597/0378e77d-3b93-bd49-0568-86f74970f9dc.jpeg">

# まとめ

結構，簡単にどの言語でも実装することが可能です．基本に帰りたい方はぜひ
paizaでkernel開発 その２

#概要

paizaでkernel開発やってみる。
paizaから、バイナリーを落とす方法を考える。

#閃きのイメージ

１、paizaで、base64エンコードする。
２、コピーして、TXTファイルにする。
３、vbsで、base64デコードしてバイナリーに戻す。

#実験

base64のgifコードをバイナリーにする。

```
R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7
```

#サンプルコード

```
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateNotExist = 1
Const adSaveCreateOverWrite = 2
Dim st
Dim data
Dim xmldom
Dim node
Dim inFile
Dim outFile
Dim cd
Dim sh
Dim str
Set sh = CreateObject("WScript.Shell")
cd = sh.CurrentDirectory
inFile = cd & "\gif.txt"
outFile = cd & "\a.gif"
Set xmldom = CreateObject("Microsoft.XMLDOM")
Set node = xmldom.CreateElement("work")
node.DataType = "bin.base64"
Set st = CreateObject("ADODB.Stream")
st.Charset = "ascii"
st.Open
st.LoadFromFile(inFile)
str = st.ReadText
msgbox str
node.Text = str
st.Close
bin = node.NodeTypedValue
st.Open
st.Type = adTypeBinary
st.Write bin
st.saveToFile outFile, adSaveCreateOverWrite
st.Close
Set st = Nothing
Set node = Nothing
Set xmldom = Nothing
msgbox "ok"


```

以上。
Chromebookを社内導入してみた話

#　はじめに
　社内でChromebookの導入が決まり、Chromebookに関して
　全く知識が無かった筆者が感じた事、対応したことについてまとめてみました。

#　自己紹介
　大学入学と同時にヘルプデスクのアルバイトを始め、オンサイトサポートや
　Ghostを使用したPC大量展開を経験。卒業後、Randstadのシステム部門に入社し
　ヘルプデスク業務やキッティング、機器の保守作業を行う。WindowsやMacを
　触ってきたが、今年からChrome OSも扱うようになる。

#　Chromebookを使う上で必要なもの
　Chromebookを法人として使う上で、主に下記のものが必要になると思います。

　<font color="#4d4dff">**Chromebook本体**</font>
　会社では Aser Chromebook C302CAを使っています。
　　[製品サイトへ](https://www.asus.com/jp/Laptops/ASUS-Chromebook-Flip-C302CA/)
　<font color="#4d4dff">**USB接続 拡張アダプター**</font>
　USB機器や画面拡張・複製、有線LANを使用するときに便利
　　[参考例](https://www.startech.com/jp/Cards-Adapters/Laptop-docking-stations/usb-c-laptop-adapter~DKT30CHV)
　<font color="#4d4dff">**Google管理コンソール**</font>
　MDMとして利用。「デバイス管理」のメニューから端末管理を行う
　<font color="#4d4dff">**Chrome端末管理ライセンス**</font>
　上記の管理コンソールを利用するために必要なライセンス


#　セットアップ工数の少なさに感動
　WindowsPCでは、言語設定、アカウント作成、プライバシーや機能のON/OFFなど
　いくつもの確認画面が表示されますが、Chromebookは<font color="red">**NW設定、企業登録設定
　Googleアカウントへのログイン**</font>の大きく3つだけで完了し、キッティングに
　掛かる時間を大幅に削減できました。長いことWindowsをセットアップしてきた
　身にとっては工数の少なさに感動しました。
![qiita1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537470/96260dd4-4f2f-a1be-6f01-6a02c92d3cdb.jpeg)
　　<font color="#4d4dff">**※Chrome OSの手順で行う「企業登録」について**</font>
　　管理コンソール上で管理する対象として紐づけを行う設定の事。

#　メリットを感じたこと
　<font color="#4d4dff">**・起動・終了が早い**</font>
　　掛かる時間も大体10秒以内！　Chromeブラウザくらいしか搭載されていないから
　　こそなせるスピーディーさです。営業担当にもすぐに使えて喜ばれます。
　<font color="#4d4dff">**・操作性がよい**</font>
　　シンプルがゆえに全般的な操作も使いやすい印象です。G Suiteとも連携しているので
　　ドライブ上に資料があればすぐにアクセスできます。
　<font color="#4d4dff">**・細かなポリシー設定ができる**</font>
　　管理コンソールを用いることで端末ポリシー、ユーザーポリシーを設定することが
　　できます。使い方の一例としてWi-Fiのプロファイルを端末ポリシーで配信、アプリ・
　　拡張機能のインストール制限、外部デバイス利用の制限などを設定することが
　　できます。
　<font color="#4d4dff">**・セキュリティ機能が高い**</font>
　　セキュリティ対策が高く、更新の手間もほとんど感じません。下記の4つがあります。
![qiita2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537470/7376f12b-d177-8f1b-b7dc-1911e2ed1e26.jpeg)
　<font color="#4d4dff">**・困ったときにはChromeリモートデスクトップを使う**</font>
　　WindowsPCをホストにしてChromebookからリモート接続を行うことができます。
　　どうしてもWindowsでないと動かないものがあるとき等に便利です。
　　**（Chromebook側）**[Chromeリモートデスクトップアプリ](https://chrome.google.com/webstore/detail/chrome-remote-desktop/gbchcmhmhahfdphkhkmpfmihenigjmpp?hl=ja)　の拡張機能をインストール
　　**（Windows側）**Chromeブラウザと上記の拡張機能を同じくインストール。
　　　　　　　　　その後、専用のホストアプリをインストール。
#　ぶち当たった課題
　<font color="#4d4dff">**・社内システムがChromeに対応していない！**</font>
　　正直こればかりはどうにもならず・・・。開発部門の対応に委ねることとして
　　Chromeに対応するよう後々改修することに。
　<font color="#4d4dff">**・プリンターがWindows対応のものしかない！**</font>
　　印刷するにはCloud Printを使うということで調べてみると、[対応するプリンタ](https://www.google.com/cloudprint/learn/printers/)　が
　　社内にはなく・・・どうするか。　別の手段で　[Windowsプリントサーバーでの設定](https://www.google.com/cloudprint/learn/printers/)　
　　というのを見つけ、社内のプリントサーバーに設定したところ上手くいきました。
　<font color="#4d4dff">**・Microsoft Officeのファイルで開けないものがある**</font>
　　おおよそのファイルはドキュメント、スプレッドシート、スライドの機能を用いて
　　閲覧・編集までできますが、特に**「マクロを含むファイル」**はVBAが動作しない
　　ものがあったり、**「パスワード保護付きのファイル」**は開封ができなかったりと
　　対応していないものもありました。

#　終わりに
　　上記の課題は有りましたが、全体的には仕事で十分使える端末であると感じました。
　　筆者も出張の際には大いに活用しています。システムのChrome対応が進んでいけば
　　社内の全てのPCがChromebookに置き換わる日が来るかもしれません。今回の記事で
　　Chromebookの導入を検討している方へのヒントになれば幸いです。
CentOS8にmicrok8sをインストールする手順

# この記事の背景
Kubernetesを勉強するために、microk8sをCentOS8にインストールしようとした。
そのためにまずはsnapdが必要だが、2019/12/13時点で、CentOSのepelパッケージには、snapd-selinuxが入っておらず単純に
`# sudo dnf install snapd`
としただけでは、エラーとなってしまう。

それに対応した記事です。
なので、CentOS8のepelでsnapd-selinuxをインストールできるようになったら、この手順は必要ないです。

# 手順の流れ
1. snapdのインストールに必要なツールをインストール
2. snapdのソースを取得
3. snapdのrpmを作成
4. snapdをローカルインストール
5. snapコマンドでmicrok8sをインストール

# 作業時のCentOSバージョン
CentOS Linux release 8.0.1905 (Core)

## 1.snapdのインストールに必要なツールをインストール
```
sudo dnf -y install go-toolset
sudo dnf -y module install go-toolset
sudo dnf -y install git spectool
```

## 2.snapdのソースを取得
この時点では2.42.2をダウンロードしCentOS8サーバに置く
https://github.com/snapcore/snapd/releases/tag/2.42.2
以下のファイル2つ
snapd_2.42.2.no-vendor.tar.xz
snapd_2.42.2.only-vendor.tar.xz

CentOS8の以下の場所に置く（任意の場所でOK）

```
# mkdir -p ~/rpmbuild/SOURCES/
# cd ~/rpmbuild/SOURCES/
# ls
snapd_2.42.2.no-vendor.tar.xz snapd_2.42.2.only-vendor.tar.xz
```

## 3.snapdのrpmを作成する
```
ファイルの解凍
cd ~/rpmbuild/SOURCES/
xz -dc snapd_2.42.2.no-vendor.tar.xz | tar xfv -
ls
snapd-2.42.2 snapd_2.42.2.no-vendor.tar.xz snapd_2.42.2.only-vendor.tar.xz

sudo dnf builddep ./snapd-2.42.2/packaging/fedora/snapd.spec -y
sudo rpmbuild -bb ./snapd-2.42.2/packaging/fedora/snapd.spec
 :
書き込み完了: ~/rpmbuild/RPMS/x86_64/snapd-2.42.2-0.el8.x86_64.rpm
書き込み完了: ~/rpmbuild/RPMS/x86_64/snap-confine-2.42.2-0.el8.x86_64.rpm
書き込み完了: ~/rpmbuild/RPMS/noarch/snapd-selinux-2.42.2-0.el8.noarch.rpm
書き込み完了: ~/rpmbuild/RPMS/noarch/snapd-devel-2.42.2-0.el8.noarch.rpm
書き込み完了: ~/rpmbuild/RPMS/x86_64/snapd-debugsource-2.42.2-0.el8.x86_64.rpm
書き込み完了: ~/rpmbuild/RPMS/x86_64/snapd-debuginfo-2.42.2-0.el8.x86_64.rpm
書き込み完了: ~/rpmbuild/RPMS/x86_64/snap-confine-debuginfo-2.42.2-0.el8.x86_64.rpm
 :
```

# 4. snapdをローカルインストール
```
# cd ~/rpmbuild/RPMS/
# ls
noarch x86_64

# sudo dnf -y localinstall ./x86_64/snap-confine-2.42.2-0.el8.x86_64.rpm
# sudo dnf -y localinstall ./noarch/snapd-selinux-2.42.2-0.el8.noarch.rpm
# sudo dnf -y localinstall ./x86_64/snapd-2.42.2-0.el8.x86_64.rpm

# sudo systemctl enable --now snapd.socket
# sudo ln -s /var/lib/snapd/snap /snap
```

# 5. snapコマンドでmicrok8sをインストール
```
# sudo snap install microk8s --classic
# snap list
Name         Version    Rev   Tracking  Publisher   Notes
core         16-2.42.5  8268  stable    canonical?  core
microk8s     v1.16.3    1079  stable    canonical?  classic
```

# おわりに
これでmicrok8sをインストールできたので、後は公式サイト等を参照してください。
https://microk8s.io/
保育士とITサポートの共通点

	
## ■はじめに	
IT知識ゼロです、ごめんなさい。
だから前職保育士と現職の共通点みつけたので書いてみます。	
	
## ■自己紹介	
前職保育士の一児の母です。	
人材派遣会社のITに所属し、現場からの問合せを受けるサポートメンバーです。	
（異動前はお仕事を紹介するコーディネーター）	
	
## ■保育士のしごと	
就業前の子供と一緒に過ごす係です。	
(ほんとはいろいろありますが。。)	
「子供と遊んで過ごす仕事っていいじゃん！」	
なんて軽い気持ちでなっちゃいましたが、以外となんでも屋だった。	
	
♪子供と遊ぶ以外にやったこと♪
　①パソコンで資料作成
　　ローマ字入力覚えたてだったので悪戦苦闘。。
　　Vista使ってたな～。
　②ミシンでお遊戯会の衣装をつくる
　　すべて手作りがモットーのコスプレ大好き保育園。
　　孫悟空の衣装を8着、動物の衣装12着などを1回の行事で作成
　　これ副業でイケるな！とおもった。
　③農作業
　　季節の作物を覚え、畑の畝を作り、種植え、追肥、草取り
　④虫強制克服
　　基本キライ。でも求められる。
　　(ひえ～きもい～！足がピヨンピヨンって！やだ～)
　　気持ちを押し殺して素手でつかみ、笑顔で渡す。
	
## ■ITのしごと	
今私がいるところはヘルプデスク？っていうんでしょうか。
なので、各種システムに関する操作等の問合せを受けてます。
でも、ここもなんでも屋だった。	
	
システムの操作の質問以外に、
運用や、他部署への質問、いろいろな要望受付。
社員の情報管理、マスタの情報処理。
研修実施やマニュアル作成。	
	
## ■共通点	
もしかして共通点「なんでも屋」！？	
それもそうでしたが、同じだな～と思ったのはこれ。
「相手のわかる言葉で話すこと」	
	
保育士の時は大人の言葉では伝わらず、
子供のわかる言葉で伝える必要がありました。	
今の現場も、相手は大人ですが、
現場からのIT系質問にIT系回答はなかなか伝わりません。
なので、現場の方が分かる言葉に置き換えて回答します。	
	
まぁ私も分からなくって、詳しいITメンバーにもらった回答をお伝えするだけなんですが、、、
だからきっと私への回答が既に置き換わった後の回答かもしれなくって
結局なにをえらそうに～！！と突っ込みがきそうですがｗｗ	

## ■おわりに	
ということで、
まだまだ脳みそいっぱい使うな～と感じたアラフォーは
来年は脳みそ活性化のため、左手で歯磨きしようかな。
"BASE"と"アドエビス "の連携について

#BASEとアドエビス の連携について
わかる方ご回答いただけると幸いです。

BASEを使ってECショップの運用をしているのですが、
今回アドエビスを使って広告効果を計測したいと思っています。

アドエビス側の指示に従って、タグの埋め込みをしたのですが、スマホ版のページに埋め込みができていないようで、PCからの流入は計測できるのですが、スマホからの計測ができません。

もし、以前BASEを使われていた方がいらっしゃれば、ご回答いただけると幸いです。
何卒よろしくお願い致します。
git hookで分散バックアップ

プッシュ後に別のWindowsの共有ディレクトリなどにクローンさせて分散バックアップを行います。

サーバーサイド(リモートリポジトリ)のhook/post-updateを作成し以下スクリプトを記述します。

to_clone_pathを変える事でクローンを作る場所を変更出来ます。

```bash:post-update
#!/bin/bash

# リポジトリの情報取得
localrepo_path=`pwd`
repo_name=`echo "${localrepo_path}" | sed "s/.*\///g"`
branch_name=`echo "${1}" | sed "s/.*\///g"`

# クローンを作成するフォルダのパスを指定
to_clone_path="//IPアドレス/共有ディレクトリのパス"

# クローン
git clone "${localrepo_path}" "${to_clone_path}_${branch_name}" -b "${branch_name}"
```
jQueryが無効なRailsでDeviseのサインアウト(GETメソッド)を定義する

こんな感じ

```ruby:config/routes.rb
Rails.application.routes.draw do
  root 'page#index'
  devise_for :users do
  end
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
end
```


いつの間にかdevice_scopeというメソッドができていた。
- [Method: ActionDispatch::Routing::Mapper\#devise\_for
](https://www.rubydoc.info/github/plataformatec/devise/master/ActionDispatch/Routing/Mapper%3Adevise_for)

```ruby
devise_for :users, skip: :all
```

とやると```devise_scope```で取捨選択して定義できる模様
社内技術カンファレンス実行委員長やったよ

# はじめに
この記事は [CyberAgent Developers Advent Calendar 2019](https://adventar.org/calendars/3981) 13日目の記事になります。

こんにちは！
昨日開催した`ADC2019(AI Tech Developer Conference 2019)`について書きたいと思います。

# ADC2019とは
CyberAgent AI Tech Stadioのエンジニアが、

  + 各開発チームの導入技術を知る機会の創出
  + エンジニア同士の横の繋がりの強化


を目的とした社内技術カンファレンスです。

始まりは2015年で、今年で5回目の開催となります！
これまでは、「Adtech Developer Conference」でしたが、
2019年9月にAI事業本部発足により、
本年より「AItech Developer Conference」としてバージョンアップしました。
今年のロゴは、横の繋がりの強化や、ネットワークをイメージして作成しました。
![ADC2019_n.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/42f24c53-f91b-d933-c869-f3073ddc38d6.png)

[▼AI事業本部プレスリリース](https://www.cyberagent.co.jp/news/detail/id=23601)

## コンセプト
1. `隣のプロダクトが技術的に何をしているか、知りたい人が知れる環境を作る`
AI Tech Stadioの中には、5つの領域を中心に事業開発をしています。
その各事業の中に多くのプロダクトがあり、チームがあります。
似た技術を使ったチームもあれば、そうでないチームもあります。
その環境の中で、より効率よく、幅広い技術についてインプットを得ることができる環境を作りたいという重いから、このコンセプトを掲げました。



2. `アウトプットファースト`
1の環境を作るためには、アウトプットしやすい環境/文化が必要と考えました。
アウトプット(登壇)することの敷居を下げるため、公募をする際に様々な工夫をしました。
その結果、50近い公募が集まりました。
例年の公募数より想定していた数を上回りました。
`アウトプットファースト`のコンセプトを判断軸に、
手を挙げていただいた方、全員に登壇していただけるよう、
当初予定していた午後から開催予定を午前中からの開催に変更しました。

また、当日の開会挨拶では、
コメントすること / 質問することも、１つのアウトプットの形なので、
1つ以上アウトプットして、皆でシェアしよう！というお話をさせていただきました！

# 当日の様子
[CyberAgent AI事業本部広報Twitter](https://twitter.com/cyberagent_ai)にて多数投稿しております！
ピックアップしますと、

社外から、2名の方に登壇いただきました！
すごく刺激的な内容で、面白かった！！と多数の声がありました！
![adc2019_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/e7ac1d53-b238-f030-6bc1-31b2487302d7.png)

![adc2019_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/d7940207-f6ad-a098-6a1a-2b5e88906965.png)

また、社内からは、AIやデータサイエンス関連で多数登壇がありました！
社内アンケートでも、かなりの高評価でした！

![adc2019_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/77c1c058-997d-3f6d-9c33-2c6e06a6679a.png)

![adc2019_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/5c6b2757-844b-d4d5-81e6-344551596386.png)

# 所感
本年は、渋谷スクランブルスクエアにオフィスが移転し、
300名+を収容できるセミナールームが自社内にあることから、例年通りホテルで開催ではなく、
自社内のセミナールームで３トラックに分けて開催しました。
オフィスと行き来がすぐできるため、準備や足の運びやすさという意味では、メリットがあったと感じています。
一方で、すぐ行き来ができるため、業務とのメリハリ部分(お祭り感)が弱くなってしまったという意見もありました。

コストとのバランスですね。
雰囲気作りの面で、カイゼンしていける部分があると思いますので、
イベント運営のふりかえりを実施し、より良いイベントにしていければと思います。

また、運営用 / スピーカー用のパーカーを作成し、当日着てきてね！とアナウンスしました。
当日の様子からもわかるように、一体感を演出できたと思います！

懇親会では、楽しめるコンテンツ(自作キーボードによるタイピングゲームやインベーダーゲームやロボットの展示)も用意し、`映え`な料理とお酒で盛り上がりました！

# さいごに
社内技術カンファレンスを通して、どんなプロダクトでどんな技術を使っているといったことを知ることができ、懇親会で繋がり、知見を共有する場になったと実感できました！
１日通しての技術カンファレンスは周期がありますが、
月１でMeetUpも運営しているので、そちらも盛り上げていければと思います！
before main

埋めるための小ネタです。

Rustのドキュメントの[usedの記事](https://doc.rust-lang.org/1.18.0/unstable-book/language-features/used.html)みたいに `.init_array` をLDCで定義したんだけど、~~最適化なしでやってもうまいこと動かんが…？みたいな疑問を持つのではないかとおもいます(もってほしい)。~~ `@used` がLDC 1.20.0時点でないから(元記事をちゃんと読んでないことがわかる)

- 環境

LinuxですがELF format使ってるなら再現できるとおもいます。~~ただOpenBSDはたぶんできない。~~ 試してないけどできるっぽいなこれは。。

```console
$ uname -msrv
Linux 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:11 UTC 2019 x86_64
$ ldc2 --version| head -2
LDC - the LLVM D compiler (1.18.0):
  based on DMD v2.088.1 and LLVM 9.0.0
```

まず普通に書くとこんな感じのコードになると思います。

```d
import ldc.attributes;

@section(".init_array")
static typeof(&before_main!"")[1] init_array = [ &before_main!"init array" ];

extern (C) void before_main(string s)()
{
    import std.stdio;
    writeln(s);
}

void main() {}
```

ですがこれだとなにも出力されません。~~どうして…~~ 上記参照。

~~これはコンパイラが `_d_dso_registry` という関数をmain実行前に呼び出すために `.init_array` を上書きしてしまうためです。
この関数はアーキテクチャごとに別実装ですが、ランタイムとかモジュールまわりの初期化とかいい感じにやってくれる感じです。~~

これは違ってました　~~、原因がわからん。 `_d_dso_registry` は `.init_array.d_dso_ctor` というシンボルでセクションに埋め込まれるしそもそもダブるようにリンカは配置しないようになっている。~~ これは一部のOSだけでLinuxとかは起きなかった。

じゃあmain前になんかやりたかったらどうするの、というと方法は(まあいくつかあるのですがmainに手を加えないとすると)２つあります。

まずは普通に `pragma(crt_constructor)` を使う方法です。これが一番素直で推奨される方法かな、と思います。
これも `.init_array` (OpenBSDではレガシーな.ctor)に配置されます。

```d
pragma(crt_constructor)
extern (C) void crt_constructor()
{
    import std.stdio;
    writeln("crt_constructor");
}

void main() {}
```

ちゃんと出力されてるんじゃないかと思います。

```console
$ ldc2 -run crtctor.d
crt_constructor
```

もうひとつは `.init_array` のさらに前で `.preinit_array` というフック可能なセクションがあるので、そこでやる方法です。

```d
import ldc.attributes;

@section(".preinit_array")
static typeof(&before_main!"")[1] preinit_array = [ &before_main!"preinit array" ];

extern (C) void before_main(string s)()
{
    import std.stdio;
    writeln(s);
}

void main() {}
```

これでもいい感じに出力がいい感じだと思います。

```console
$ ldc2 -run preinit.d
preinit array
```

注意点はどちらの場合であってもGCを必要とする処理やモジュール初期化処理を前提とした処理ができない点です。
GCの初期化処理は `pragma(crt_constructor)` で実装されているので。(`pragma(crt_constructor)` を使ってフックする場合は順序未規定になる気がするが、それに依存したコードをそもそも書くべきではない)

実行順は `.preinit_array` → `pragma(crt_constructor)` → `main` → … となるので([参考](http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html)) うまいこと実行順に気をつけて書いてください。

ちなみにLDCでは `crt_constructor` はGCC拡張の `__attribute__((priority(N)))` のように優先順序が与えられるようになっています。

```d
pragma(crt_constructor, 2)
extern (C) void crt_constructor_2()
{
    import std.stdio;
    writeln(__FUNCTION__);
}

pragma(crt_constructor, 1)
extern (C) void crt_constructor_1()
{
    import std.stdio;
    writeln(__FUNCTION__);
}

void main()
{
    import std.stdio;
    writeln("main");
}

```

昇順になっていることが確認できます。

```console
$ ./ctordtor
ctordtor.crt_constructor_1
ctordtor.crt_constructor_2
main
```

ではでは。
Goで地形生成ツールを作る

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

カレンダーも折り返し地点ですね。

# はじめに
[Goで画像生成をして遊んでいたら](https://qiita.com/tomowarkar/items/2aea52ac512e895b0a42)もう少し本格的なものを作ってみたく、機能を追加しつつツール化してみました。

完璧自己満足案件ですね😸

ランダムドットの生成に加え、以下記事を参考に中点変位法を用いたマインクラフトのようなワールドマップの生成を手軽にできるようにしました。

[中点変位法 世界生成🌏](https://qiita.com/Gaccho/items/d0748d630b311f620f92)

現状ランダムドット画像の生成、中点変位法を用いた画像生成の二つの機能しかありませんが、ゆるりと機能追加していけたらなーという次第です。
# 使い方
### ソースコード
<a href="https://github.com/tomowarkar/biome"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/tomowarkar/biome.png" width="460px"></a>

### go get
```
go get -u github.com/tomowarkar/biome
```
# コード
### ランダムドット画像生成
```golang
package main

import "github.com/tomowarkar/biome"


func main() {
	var seed int64
	scale := 100

	d := biome.NewDicts()
	d.Set(0, biome.Khaki)
	d.Set(1, biome.Darkgoldenrod)
	d.Set(2, biome.Royalblue)
	d.Set(3, biome.Seagreen)

	b := biome.NewWorld(5, 8)
	b.RandIntn(len(d), seed)

	err := b.ToPng(scale, d, "image")
	if err != nil {
		panic(err)
	}
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235435/198cd00c-cd0f-3436-e465-886f8c04becc.png)

### 中点変位法を用いたワールドマップ生成
```golang
package main

import "github.com/tomowarkar/biome"

func main() {
	var seed int64
	width, height, scale := 48, 32, 10
	world := biome.Flactal(height, width, seed)
	d := biome.DefaultDicts()
	world.ToPng(scale, d, "image")
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235435/8ee4442b-e594-b875-16fe-68d8585fad3d.png)

```golang

width, height, scale := 240, 160, 2
```
ワールドマップのスケールを変更すると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235435/b461ba79-eaeb-c26f-33ce-3b388eae9894.png)
でん！！！

# おわりに
Goの`interface`やポインタとはあまりお友達ではなかったのですが、このツールを作るにあたって`interface`やポインタを考えながら使う必要ができ、少しはお友達になれた気がします。

2つの機能しかありませんがそれらしさが出てとても良き良きでした。


以上明日も頑張ります！！
[tomowarkar ひとりAdvent Calendar Advent Calendar 2019](https://qiita.com/advent-calendar/2019/tomowarkar)
firestoreのreferenceとかsnapshotで混乱したので整理してみた

firestoreを使ってて、あれコイツは`data()`持ってないんだっけ、あれコイツには`update()`できないんだっけ？と混乱したので整理してみました。

# サマリ

```js

// これはDocumentReference
// ただの参照であって実体はない
const shopDocRef = db.collection('shops').doc('1');

// add, set, update, deleteなどの操作は
// Referenceに対して行う
await shopDocRef.update({name: "レストラン品川"});

// referenceに対してget()で
// 実体であるDocumentSnapshotを得る
const shopDoc = await shopDocRef.get();

// DocumentSnapshotoにdata()すると
// データを取得できる
const shop = shopDoc.data();
```

# Reference
referenceはただの参照。ドキュメントやコレクションへのパス情報だけで、中身を持っていない。  
データの追加、更新、削除はreferenceに対して行う。

## CollectionReference
コレクションへの参照。

```js
// CollectionReference
// - id
// - path
// - parent
const shopsCollectionReference = db.collection('shops')
 ```
 
## DocumentReference
ドキュメントへの参照。

 ```js
// DocumentReference
// - id
// - path
// - parent
const shopDocumentReference = db
  .collection('shops') // ここまででCollcectionReferenceを取得
  .doc('1');
```


## 追加、更新、削除はreferenceに対して行う

特定のドキュメントの更新、削除

```js
const shopDocumentReference = db
  .collection('shops')
  .doc('1');
 
// ドキュメント更新
await shopDocumentReference.update({name: "レストラン品川 1号店"})

// ドキュメント削除
await shopDocumentReference.delete()
```

コレクションにドキュメントを追加。下の例ではidを自動採番。

```js
const shopsCollectionReference = db.collection('shops');

// ドキュメント追加
await shopsCollectionReference.add({name: "恵比寿コーヒー", place: "恵比寿"})
```

idを指定したい場合の書き方


```js
// ドキュメントidに"4"を指定
const shopDocumentReference = db.collection("shops").doc("4");
// ドキュメント追加
await shopDocumentReference.set({ name: "恵比寿コーヒー", place: "恵比寿" });
```



# Snapshot
中身の実態。
referenceに対して`get()`することで取得できる。
`get()`は非同期に実行されるので`await`で実行する。

## DocumentSnapshot
ドキュメントの実態。
`.data()`メソッドでデータのオブジェクトを取得できる。

```js
// DocumentSnapshot
// - exist
// - id
// - ref
const shopDocumentSnapshot = await db
  .collection('shops')          // ここまででCollcectionReferenceを取得
  .doc('1')　// ここまででDocumentReferenceを取得
  .get();                      // snapshotを非同期で取得

// data
const shop = shopDocumentSnapshot.data();

// DocumentReference
const shopDocumentReference = shopDocumentSnapshot.ref
```


# Query関連

検索で使う。

## Query
ただの検索条件の定義。まだ何も中身を取得していない。

```js
// Query 
const query = db
  .collection('shops')
  .where('place', '==', '品川');

```


## QuerySnapshot

`Query`に対して`get()`すると検索を実行して中身を取得する。
その中身が`QuerySnapshot`。

`docs`という配列を持っていて、この配列に`queryDocumentSnapshot`が複数格納されている。
`queryDocumentSnapshot`は`DocumentSnapshot`とほぼ同じぽい。

```js
// QuerySnapshot
// - docs (Array)
// - empty (bool)
// - query (Query)
// - size (number)
const querySnapshot = await db
  .collection('shops')
  .where('place', '==', '品川')
  .get()

if(querySnapshot.size > 0){
  // DocumentSnapshotと同じ
  const queryDocumentSnapshot = querySnapshot.docs[0]
  // data
  const shop = queryDocumentSnapshot.data()
  // DocumentReference
  const bookDocumentReference =  queryDocumentSnapshot.ref 
}

```


#参考URL
[Cloud Firestore にデータを追加する](
https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja#node.js)
gitコツコツ勉強法（半年で使えるようになるまで）

# 概要
本文は筆者がgitをそこそこ使えるようになるまでの道のりです。
git未修者に多少の参考になればと思い、自分が勉強したことを記載します。

# やったこと
* udemy見た
* 書籍で概要を学んだ
* N予備校で実際に使った
* vscodeのプラグインで理解した概念をさらに楽に使えるようにした

以下ではそれぞれについて記載していきたいと思います。
## udemy見た
git関係では以下2つを見ました。なぜ見たかというと、テキストで勉強するにはあまりにハードだったからです。
(お恥ずかしい話、[猿でもわかるgit入門](https://backlog.com/ja/git-tutorial/)を挫折した人間なので)

### はじめてのGitとGitHub
https://www.udemy.com/share/100dDgBUAac19SQX4=/
- 無料なのでとりあえず見てみるといいと思います

### もう怖くないGit！チーム開発で必要なGitを完全マスター
https://www.udemy.com/share/1004bOBUAac19SQX4=/

**なお、udemyは定価で買わずに検索かけるなり、セールス期間を利用して、千円代で動画を購入することを強くお勧めします。**

## 書籍で概要を学んだ
### [独習Git](https://amzn.to/2COgPY7)（アマゾンリンク張っちゃってます）
計3周やりました（合計で30時間くらい）。
1周目は全て馬鹿丁寧に。
2周目はvsCode使って同じ作業をどうすればできるかを調べながら。
3周目は念のための復習で。

なお、私の場合は、章末の課題については気が向いたらやる感じでした。
あと、5章のGitGUIと19章のサードパーティー、それからちょくちょく挟まれるGitGUIでやる方法は、よほどのことがない限り使う機会がないのでやらなくてもいいと思います。

また、sourcetreeに関する書籍も何冊かやりましたが、vscodeなどのエディタには似たような機能があるため、何か特別な事情がない限りオススメはしないです。

## N予備校で実際に使った
もしもあなたが実際に仕事で接する機会がない場合、独習gitでも触れはしますが、N予備校で実践的な使い方のレクチャがあるのでそちらで学んでみることをお勧めします。
なお、2章の11「GitHub で Web サイト公開」から16「ソーシャルコーディング」までに詳しい解説があり、以降でも課題の提出はgithubを使うため、非常に実践的です。

https://www.nnn.ed.nico/pages/programming/

## vscodeのプラグインで理解した概念をさらに楽に使えるようにした
デフォルトのソース管理、それから、リモートやブランチ、それからスタッシュについては[Git Lens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)ってプラグイン使ってください。
詳しい使い方はこちらの記事が参考になると思います。

[VSCodeの機能で最低限必要なGit操作をしたい！]
(https://qiita.com/mnao305/items/b3c5f5943066a0bb8e2e)

# 結論
gitは以下に紹介する本と動画でコツコツ勉強すると半年で現場で使用するのに先輩の助けがいらないくらいに使えるようになりますのでめげずに頑張りましょう。
WordPressに入れておきたい最低限のプラグイン

WordPressというものを知って、最初は片っ端からプラグインを入れまくってましたが
触っているうちに最低限のプラグインだけ入れておいた方が管理も楽だな…と、やっと気づけたので
よく使うプラグインをまとめてみました。

相性の悪いプラグインとかも多いですもんね…。
入れすぎて「プラグイン更新」や「どのプラグインと相性が悪いのか」とか調べるのは結構大変なので、できるだけ少なくしていきます。

***

**WP Multibyte Patch**
日本語でWordPressを利用する時に文字化けを防ぐプラグイン。
入れてない時でも文字化けは起こりませんでしたが、稀に文字化けをするみたいなので入れておくと安心。

***

**Contact Form 7**
お問合せフォームを簡単に設置する事ができるプラグイン。
利用者が多いのでカスタマイズ方法やエラーが出ていてもネットに解説が沢山あるので扱いやすい。
WordPressは海外製プラグインが多い中、これは日本製プラグインなので安心して使用する事ができる。
ホームページにはお問合せフォームを必ずと言っていいほど設置しますし、ブログ運営でもアドセンス審査を出すにもフォームは必要ですね。

***

**Easy FancyBox**
記事や固定ページ内の画像を別窓で開かずにそのページにポップアップで表示する事ができるプラグイン。
プラグインを有効化にして、画像にリンクを付けるだけで勝手にポップアップ表示（拡大）してくれる優れもの。
画像を拡大しようとしてクリックすると、別窓に画像だけ開くのが閲覧者に親切じゃないので、拡大してほしい画像を張り付ける事が多い人は入れる事をおすすめします。

***

**SiteGuard WP Plugin**
ログインURLを変更できたり、不正アクセスのリスクを減らす事ができるプラグイン。
WordPressのログインURLはhttp://……/wp-login.phpで、誰でもログイン画面に行くことが出来てしまいます。
このログインURLを好きな英数字に変更する事が出来るので、ログイン画面を隠す事ができます。
「ログイン失敗を繰り返す接続元を一定期間ロック」できたり「ログインページ、コメント投稿に画像認証を追加」する事もでき、日本製プラグインで安心です。

***

~~　**a3 Lazy Load**　~~
~~　記事や固定ページ内の画像を遅延読み込みしてくれるプラグイン。　~~
~~　遅延読み込みをするだけで、サイトの表示スピードが上がり、訪問者の離脱を防ぐことができます。　~~
~~　サイトは早いに越したことない！　~~
~~　このプラグインは有効化するだけで勝手に画像を遅延読み込みしてくれます、最高。　~~

【2021年2月追記】
WordPress 5.5からプラグインを使用しなくても自動で遅延読み込みしてくれるようになりました。

***

**Google XML Sitemaps**
サイトマップを自動で作成してくれる優れもの。
サイトマップが設定されていないと検索エンジンに反映（インデックス）されるのに時間がかかったりするので
必ず設定しておくことをおすすめします。

***

この5個のプラグインは必ずと言っていいほど入れています。
「プラグインは〇個まで！」と自分の中で個数を決めた方が
無造作にプラグインを入れるのを防げるんじゃないかな～と思います。

紹介したものでも、プラグインを使用しない方法も多数存在するので
気になるものは勉強のためにもプラグインを使用せず実装出来るようになりたいですね。

WordPressテーマによっては最初から入ってる機能とかもあるので
そのあたりは使用してるテーマを確認してください。
SSO(シングルサインオン)の仕組み

#SSOとは
　- **一度ログインしたら**ほかのツールでも認証してくれる便利もの
　- 例えば**windowsにログインしたら自動で認証されてソフトを使える**
　- 大きく分けて2種類の認証方法がある
　　- ユーザーの代わりにパスワードを入力する**代行入力方式**と呼ばれるもの
　　- 指定された認証サービスで認証が終わっている時にアクセスを可能にする**信頼認証方式**と呼ばれるもの 
　　- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11615.html)
　
#実現方法
　使用した認証方法は4つ(様々な会社の認証システムの開発だったので4種類使いました。基本1つで大丈夫)

　- サーバーエージェント方式
　- リバーシプロキシ方式
　- 代理認証方式
　- フェデレーション方式

　各方法にそれぞれメリットデメリットがあります。ネットワーク構成の複雑さ、クライアントの環境、スケールアウトしなければならない...などなど。その時に合った方法が必要です

　詳しい実現方法などは以下のサイトが見やすかったです
　[シングルサインオンの仕組みと方式](https://boxil.jp/mag/a2411/#2411-1)
Rails3.2でiCalendarを使う

booked Schedularで予定をOutlookに取り込んだら便利だったので、Railsでもやりたくなった。

#配布元
https://github.com/icalendar/icalendar

ググっても日本語で記事を書いている人が少ない。なぜ？

#インストール
windowsでやってます。

```
> ruby -v
ruby 1.9.3
> gem install icalendar -v "2.4.1"

> bundle install
```


#苦労したところ
先に苦労した書いておきたい。
##ical形式とは？
まずHTMLじゃない。ical形式ってところから学ぶことになる。
[カレンダーに使われるiCalendar形式について part1](https://qiita.com/TomOse/items/31b5fb4782f06d19af79O)

##ブラウザでアクセス
そしてHTMLじゃない。ブラウザでアクセスしてもicsファイルをダウンロードする。ダウンロードしたものが正しい記述なのか簡単に判断できない。

##Outlookに取り込むまえ
予定表を開く　＞　インターネットから
URLを入力してもへっぽこコードだと開かない。Railsのエラーもよくわからん。

##ドはまりした認証
hoge/export_eventsってな名前で作成していたが、auth（認証ページ）で引っかかっていた。（気が付くのに時間が掛かった・・・）

```
before_filter :auth, :except=>[:export_events]
```

例外にしておく必要がある。（特定の人にだけ公開ってなことになると、どうすれば良いのかわからない）

#コード
サンプルが少なくてお試しコードを作るのも一苦労した。
##お試しコード
まずはOutlookに表示させることだけを考える。いろんな人の英知を参考にしたコードです。

```
  def export_events()
    require 'icalendar'
    cal = Icalendar::Calendar.new
    
    cal.append_custom_property("X-WR-CALNAME;VALUE=TEXT", "俺のカレンダー")
    cal.timezone do |t|
      t.tzid = 'Asia/Tokyo'
      t.standard do |s|
        s.tzoffsetfrom = '+0900'
        s.tzoffsetto   = '+0900'
        s.tzname       = 'JST'
        s.dtstart      = '19700101T000000'
      end
    end

    cal.event do |e|
      e.dtstart     = Icalendar::Values::DateTime.new('20191228T133000')
      e.dtend       = Icalendar::Values::DateTime.new('20191228T153000')
      e.summary     = "Meeting with the man."
      e.description = "Have a long lunch meeting and decide nothing..."
    end

    cal.publish
    headers['Content-Type'] = "text/calendar; charset=UTF-8"    
    render :text => cal.to_ical
  end
```
dtstartとdtendは近い日時にしておかないと表示を探さないといけない。地味にめんどい。
Outlookに取り込めたらこっちのモンです。

##改造コード
`cal.event do |e|`　このあたりを改造する。

日時形式を合わせる必要がある。改行コードは「\n」だった。


```
# params[:piyo]とかも使えたので、いくらでもやりようがある。
# hoge/export_events?piyo=fugafuga　とか
    reservations = Hoge.all #実際には本日から1ヵ月ぐらいの範囲にした
      
    reservations.each do |res|
      cal.event do |e|
        e.dtstart = Icalendar::Values::DateTime.new(res.responding).strftime("%Y%m%dT%H%M%S")
        e.dtend = Icalendar::Values::DateTime.new(res.responding + 1.hour).strftime("%Y%m%dT%H%M%S")
        e.summary = res.member_name
        e.description = res.content + "\n\n" + res.memo
      end
    end
```

こんな感じで予定を作ります。

#参考
[Sinatra + icalendar Gemで予定をWebで配信するサンプル](https://qiita.com/mktakuya/items/a181aa56491c2fdc5625)
[RubyでiCalの作成とGoogleCalendarでの公開](http://rochefort.hatenablog.com/entry/2014/09/09/073000)

#追記
outlookに設定してからサーバのログを眺めると30分毎にアクセスがあります。
Go言語でS3から直接ダウンロードするURLを発行する時にファイル名を差し替える

ちょっとハマったのでメモ

差し替えのファイル名は"response-content-disposition"にセットする必要がある。
object inputのparamでResponseContentDispositionを指定できるようなのでそちらで指定する

```go

  svc := s3.New([s3 setting params])

  // 日本語ファイル名にしたい場合はURLエンコードが必要
  fileName := fmt.Sprintf("attachment; filename=%s", url.QueryEscape("ファイル名"))

  params := &s3.GetObjectInput{
    Bucket:                     aws.String([bucket name]),
    Key:                        aws.String([key]),
    ResponseContentDisposition: &fileName,
  }

  req, _ := svc.GetObjectRequest(params)
  // 期限付きURLを発行
  downloadURL, err := req.Presign(10 * time.Minute)
```

参考にさせていただいたページ
https://qiita.com/kitar/items/166896357f50f4fe0a95
https://stackoverflow.com/questions/40434525/download-s3-file-with-a-different-filename-than-the-bucket-key
VisualStudio2017 Ver15.8系でテストが実行できない


VisualStudio2017 Version15.8.6にて、こんなサンプルテストを記載した。

```csharp
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject2 {
    [TestClass]
    public class UnitTest1 {

        [TestMethod]
        public void TestMethod1() {
            Assert.Equals("aaa", "aaa");
        }
    }
}
```
そうしたところ、以下のようなWarningメッセージが表示された。

```
[2019/11/26 17:46:46 Informational] テスト メソッド 'UnitTestProject2.UnitTest1.TestMethod1' を実行しています
[2019/11/26 17:46:46 Informational] ------ テストの実行が開始されました ------
[2019/11/26 17:46:47 Warning] No test is available for testcase filter `FullyQualifiedName=UnitTestProject2.UnitTest1.TestMethod1` in C:\Users\xxxx\UnitTestProject2\bin\Debug\UnitTestProject2.dll
[2019/11/26 17:46:47 Informational] ========== テストの実行が完了しました: 0 が実行されました (0:00:00.5789996) ==========
```

VisualStudioの不具合の模様。
Ver16.2以降では解消されているようなので、さっさと最新化。
https://developercommunity.visualstudio.com/content/problem/311537/unit-testing-cannot-findexecute-test-cases-anymore.html

最新化したところ、無事にテスト実行ができた。