OmniAICreator/Qiita-1.07M huggingface dataset:
Rubyを使って予約システムを使いやすくハックしよう

# はじめに

こんにちは。GMOアドマーケティングのyoshishinです。
皆さんは普段、よく使うWEBサービスなどありますか？
自分は最近、予約システムをよく使うようになったのですが、毎回同じ操作をしており、効率的ではないと感じています。
多くの人が使いやすいように作られているとは思うのですが、人によって感じ方は様々で、手順が決まっているのであればいつもの設定をボタン一つでできたら便利ですし、中には自分専用の画面がほしかったりするかもしれません。
今回はこのような予約システムを使いやすくするためのハックを考えていきたいと思います。

# 目標

予約システムから必要な情報を取り出し、使いやすいJSON形式に整形して任意のレスポンスを返すことを目標とします。
JSON形式であれば、データを元に画面を作ったり、思い通りに操作することが容易となります。

## 開発環境

まずは開発環境を整えます。
今回メインで使うライブラリはnokogiriです。
HTMLという素材からノコギリで必要なものを切り出していくイメージですね。
Rubyが使える状態であれば、以下のコマンドでインストールできます。

```
gem install nokogiri
```
Railsを使う場合はこのgemが含まれているため、bundle installすることで追加されます。

公式サイト
http://www.nokogiri.org/

以下、公式サイトのサンプルです。

```
require 'nokogiri'
require 'open-uri'
# HTMLドキュメントを取得し、解析
doc = Nokogiri::HTML(open('https://nokogiri.org/tutorials/installing_nokogiri.html'))

puts "### Search for nodes by css"
doc.css('nav ul.menu li a', 'article h2').each do |link|
  puts link.content
end
puts "### Search for nodes by xpath"
doc.xpath('//nav//ul//li/a', '//article//h2').each do |link|
  puts link.content
end

puts "### Or mix and match."
doc.search('nav ul.menu li a', '//article//h2').each do |link|
  puts link.content
end
```

xpass,cssを使い、レスポンスを確認しながら目的のデータを取得します

## 解析

次に解析です。
Chromeであれば、画面を右クリックして、検証を選択することで、HTML構造を確認できます。
HTMLの構造から特徴をまとめていきます。

![スクリーンショット 2019-12-18 22.59.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316327/41817231-fdff-5546-41c9-90dddebcaf83.png)

普段使っているWEBサイトであれば、どういう構造で、どんなデータが欲しいのかはすぐに想像できると思いますし、何らかの不満を感じているのであれば、こうすれば使いやすくなるという改善案もあると思います。

対象システムでは日にちごとにいくつかの時間があり、時間毎に予約枠を持っているという特徴がありました。

## 設計

専用画面を作り、登録した設定情報を元に予約できるようになれば便利になると思うので、JSON形式のレスポンスを返し、そこから画面を表示できるようにしていきます。
解析時の特徴から、以下のようなJSON形式にすると使いやすそうなので、データを整形していきます。

```
[{"day"=>"12/23", "times"=>[
  {"time"=>"12:00", "stock"=>0},
  {"time"=>"12:15", "stock"=>0}, {"time"=>"12:30", "stock"=>0}, {"time"=>"12:45", "stock"=>0},...
]
```

## データ取得

理想の形が定まっているのであれば、あとはnokogiriでひたすらデータを切り出し、設計したJSON形式にデータを格納していきます。
作ったデータを呼び出すメソッドを用意すればJSON API化は完了です。

対象サイトをスクレイピングして整形したJSONを返し、それをRailsの画面で表示してみました。

<img width="918" alt="スクリーンショット 2019-12-21 6.32.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316327/627dffc0-fcdd-c342-75d8-fdfd3a420dc1.png">


# まとめ

以上の手順でJSON API化することができました。
ここまでできれば後は使いやすい画面を作るなり、設定に従った自動予約、チャットシステムとの連携など、思い通りに操作することができると思います。
予約システムだけでなく、他の仕組みにも応用できると思うので、毎日多くの時間を費やしているシステムがあれば、使いやすくハックすることも検討してみてはいかがでしょうか？

注意点として、実際に使うタイミングで自動予約するのであれば手動でアクセスするのと比べて負荷は変わりませんが、バッチを使った予約の空き枠通知など、定期的にアクセスする実装はサーバーの負荷になってしまうため、控えた方がよいと思います。

以上です。

明日は、[M.Nさん](https://techblog.gmo-ap.jp/author/na-ka/)による「TAXELの回遊率を少しだけ最適化した話」です。
引き続き、[GMOアドマーケティング Advent Calendar 2019](https://qiita.com/advent-calendar/2019/gmo-am) をお楽しみください！
lambda_handler外のグローバル変数に気をつけよう(datetime)

# はじめに
ジョブが作成されてからLambdaが実行されるまでの間の時間（滞留時間）を取得する
Lambdaを作成していた時に
現在日時を取得するためにdatetimeを使用していたのですが、
そこで「AWS Lambdaは関数インスタンスを再利用」というのに見事にハマったので、
記事にしてみたいと思います。

# 最初に作成していたコード
まずLambdaが実行された現在日時を取得するための
コードを簡略化したものが以下になります。

```.py
from datetime import datetime

now = datetime.now()

def lambda_handler(event, context):
    method_a()

def method_a():
    method_b()

def method_b():
    method_c()

def method_c():
# xはジョブの作成日時を表しています。
   time = now - x
   print(data)
```

- ジョブの作成時刻を`x`
- 現在時刻を`now`
- 滞留時間を`time`

として表しています。

時刻を表すnowをグローバル変数として宣言して
どのメソッドでも使えるようにしてました。

#ローカルでは成功したけど…
ローカルでは滞留時間を取得できたので、
そのままビルドデプロイしてLambdaを作成しました。
最初のLambdaのテストも成功して問題はありませんでした。
### よし大丈夫だ！もう一回テストして確認しよう…
### あれ！？滞留時間がおかしい！！！！！！

１回目で上手く取得できていた滞留時間が
２回目以降上手く取得できませんでした。

何回やっても`time`がおかしい。

そこでまたビルドデプロイして
Lambdaを更新させてみたところ上手くいきました。

しかし、また２回目以降はダメでした。

# 原因は
そこで原因調査のために色々調べていると
[こちら](https://hacknote.jp/archives/50525/)の記事に出会いました！

ずばり原因は、lambda_handler外で宣言したグローバル変数の`now`でした。

どうやらLambdaはパフォーマンス向上のために
関数のインスタンスを再利用するみたいです。

https://aws.amazon.com/jp/lambda/faqs/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510859/a6717385-ac60-568d-a7fc-e40a5b9018bb.png)

つまり一回目に取得した`now`の日時がキャッシュされ
2回目以降も同じ値が再利用されていたみたいです。

常にLambdaの関数インスタンスは新規で作成されているものだと
思っていたので、全く気づきませんでした！！

# lambda_handler内にグローバルに変数を置きたい

原因を理解したところで
とりあえず`now`を`lambda_handler`内に置きました。
これでLambdaが実行されるたびに新しく`now`の日時を取得してきてくれます。

```.py
from datetime import datetime

def lambda_handler(event, context):
    now = datetime.now()
    method_a(now)

def method_a(now):
    method_b(now)

def method_b(now):
    method_c(now)

def method_c(now):
# xはジョブの作成日時を表しています。
   time = now - x
   print(data)
```
この形でも実行できるのですが、
こんなにメソッドを経由して渡すのはかっこ悪いので
以下のように修正しました。

```.py
from datetime import datetime

def lambda_handler(event, context):
    global now 
    now = datetime.now()
    method_a()

def method_a():
    method_b()

def method_b():
    method_c()

def method_c():
# xはジョブの作成日時を表しています。
   time = now - x
   print(data)
```

これで無事、2回目以降も
ちゃんと`now`が実行した日時を取得してくれるようになり
`time`も上手く取得できました。

# まとめ
Lambdaの関数インスタンスの再利用については
初耳だったので、とても勉強になりました。

あとは、グローバル変数はとても便利ですが
思わぬバグを引き起こす原因になりやすいということを
身を持って実感しました。

使い方には気を付けていこうと思います。
overlayfs の mount

Fedora 30 の Silverblue をデスクトップ環境として使ってみている。

rpm の導入については rpm-ostree を使えば良いが、
ostree の機能の為 /usr が read only になっている為にそれ以外で
/usr に書き込みを行ないたい時は困る。

ostree admin unlock ではその変更が失われてしまうので、
/usr に overlayfs を使ってみることにした。

1. オーバーレイ用ファイルシステムを作成し、 /mnt/overlay-usr に mount する。
2. /mnt/overlay-usr/UPPER と /mnt/overlay-usr/WORK を作る。
3. /usr 上に mount する。

```
# mount -t overlay overlay -o lowerdir=/usr,upperdir=/mnt/overlay-usr/UPPER,workdir=/mnt/overlay-usr/WORK /usr
#
# mount |fgrep overlay
/dev/md122 on /var/mnt/overlay-usr type btrfs (rw,relatime,seclabel,space_cache,subvolid=5,subvol=/)
overlay on /usr type overlay (rw,relatime,seclabel,lowerdir=/usr,upperdir=/mnt/overlay-usr/UPPER,workdir=/mnt/overlay-usr/WORK)
```

取り敢えずこれで目的は達したように見える。

これを起動時に mount したいと思って /etc/mtab を参照して、/etc/fstab に下記のように書いてみた。

```
overlay /usr overlay rw,seclabel,relatime,lowerdir=/usr,upperdir=/mnt/overlay-usr/UPPER,workdir=/mnt/overlay-usr/WORK 1 3
```

所が、うまく mount されない。はて？

起動後手動で

```
# mount /usr
```

する分には問題無く mount されるのだが？

色々厄介なようなので、今回は /etc/init.d/ 下のスクリプトに、

```
#
/usr/bin/mount | /usr/bin/fgrep "overlay on /usr"
if (( $? != 0 )); then
    /usr/bin/mount /usr;
fi
#
```

と書き足して済ませることにしました。
wordpress+Stripeでカンタンサブスク決済

stripeアドベントカレンダー12/20です（日にちが跨いでゴメンナサイ！）＆簡単なネタで恐縮です！

WordPressのプラグインで実装できそうだなー、そのうちやりたいなーと考えている方へ！
有料のプラグインという方法もあります。

##WP Full Stripeプラグインを購入する
https://codecanyon.net/item/wp-full-stripe/5266365
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/a6fc2bb1-3806-8f79-a871-b9003311b354.png)

大体5000円ちょっとで購入できます。WordPress側でガリガリ書くこともできますが、手っ取り早くプラグイン購入します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/9ab1d84b-9a76-cfff-0ed7-0fedd5dcfa01.png)
管理メニューのFull StripeからSubscriptionsを設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/590a95db-d1c7-1a51-f02a-9f3ed12c3268.png)
カスタムフィールドで通常の項目以外に入力項目を増やせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/725ccab4-70b1-6b2a-52d0-95a68547760d.png)
申し込み後のリダイレクトページの指定も可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/eac8f574-86be-af20-74d0-77468a5c91b0.png)
後はショートコードで固定ページに埋め込むだけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/1f5e0a61-3233-3538-35a0-bf28fbb5ebac.png)
結果を確認してみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/eaa201dc-bf2e-b005-4863-64d8e31a7a4b.png)
OK!ちゃんとStripeの決済画面と連携できています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/62b32f4f-c248-c50f-8b3a-c225e25aa30b.png)
管理画面でも決済の履歴が確認できます。

##と、いうわけで！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76660/c3512bf3-5489-fdf3-3b2c-b05f12767b0b.png)

サクッと決済してもらい、２週間立たずに口座に振り込みがありましたー。
管理画面も充実しているので、WordPress×Stripeでサブスク払い、オススメです！
返金や解約もStripeの管理画面からできますよ！
あなたにおすすめの商品があります。

#はじめに
皆さんはタイトルの文言に見覚え、聞き覚えはないでしょうか？？
オンラインショッピングやYoutubeなどを利用すると似文言をよく見かけますね。
いわゆる**レコメンド機能**ですね。
この記事ではレコメンドの意義や何を根拠にユーザーへ発信されているのかを、簡単に説明していこうと思います。

##レコメンドの意味
そもそも何故レコメンド機能が多くのサービスに実装されているのかを考えてみましょう。
サービスには何かを渡す人と受け取る人がいます。
説明する必要があるか分かりませんが例を挙げていきます。

今この記事を書いている私の傍らにはBiSHがのライブDVDがあります。
これは借り物ですが、仮に私がネットで買ったものとしましょう。
するとこういう関係になります。

提供者:Amazon
受領者:私
提供されるもの:BiSHのライブDVD
(実際にAmazonで買い物をするとAmazonと契約している店舗から
その商品が送られたりしますが、今回は関係ないので無視します。)

私としては欲しいものが手に入るなら、Amazonで買わなくても問題ありません。
極論、どのサイトで購入してもいいわけです。
しかし、Amazonとしては私にリピーターになってもらい、お金をどんどん落としていってほしいわけです。
そんなAmazonの顧客を逃がさない作戦の一つが、レコメンド機能というわけです。

レコメンド機能を使って、商品をカートに入れた時や購入後に
「ねぇねぇ、君ヤングオオハラもええで？」と私にプッシュしてあげるわけです。
それによって「おっなんこれ、これも買ったろ」と私に思わせればAmazonの勝ちです。
(別に買ってしまったらユーザーの負けというわけではないのであしからず…)

Amazonは売り上げの増加、顧客の囲い込み、顧客満足度の向上等ができ、ユーザは良い顧客体験(UX)を得ることができ、ほくほくになるという感じですね。
お互いwinwinの関係ですね。winwinの関係です。

##レコメンドの種類
次にレコメンド機能の種類について説明します。
・同じコミュニティの中でのレコメンド(協調フィルタリング)
・あなた個人に対するレコメンド(コンテンツ単位のフィルタリング)
・サービス提供側の策略
(細かく分けると、ほかにもあると思いますが割愛します。)

サービス側の策略はあれです…在庫処分とかそういうやつです。
なので残りの2つについて掘り下げて説明します。

###協調フィルタリング
協調フィルタリングはコミュニティの動きに基づいてレコメンドを行います。
先ほど例を出したAmazonやYoutubeが分かりやすい例だと思います。
その辺を例に挙げながら協調フィルタリングの長所と短所を説明します。

**長所**
各ユーザーの行動や趣味趣向に基づいて、類似したデータを用いてレコメンドすることが出来ます。
AmazonなりYoutubeなりのサービスを利用する際ににユーザー登録(性別、年齢、国籍等)を行うと思います。サービス登録者の情報と履歴を分析することで「この人と近いユーザー情報でこの商品を買った人はあの商品もよく買う」というような分析をすることができるわけです。
コミュニティ内の人と人のデータを結び付け、顕在的な需要から潜在的な需要まで引き出せる可能性を秘めている強力な機能と言えます。

**短所**
とても強力な機能に見えますが、新規ユーザに弱いです。
新規ユーザーはレコメンドを行うためのデータが少ないため、レコメンドすることができない(できても極端に精度が低い)といった短所があります。
リピーターになれば解消されますが、大きな短所と言えるのではないでしょうか。

Youtubeのおすすめに見たこともない分野の動画がたまーに紛れ込むのは、あなたと同じような情報を持った多くのユーザーがその動画を見ているのでしょうね。

###コンテンツ単位のフィルタリング
コンテンツ単位のフィルタリングは、あなた個人の履歴と類似性に基づいてレコメンドを行います。
こちらも例を挙げながら長所と短所を説明します。

**長所**
あなた個人の履歴と類似性からレコメンドを行っているため、突飛なものをレコメンドすることがありません。
例えば「BiSHのライブDVD」を買ったとすると、「BiSH」「音楽」といった情報を抽出できます。
コンテンツ単位のフィルタリングを行うと、私へのおすすめは「BiSH」「音楽」に関したものになり、「名探偵コナン」のような商品がおすすめされることはないわけです。
(ごめんね、コナン君)
このことからユーザ個人に寄り添ったレコメンドをできることが長所と言えます。
また新規ユーザにも強いです。

**短所**
ユーザーがはっとするようなおすすめが出来ないことが短所と言えます。
「長所は短所」とはよく言ったものでユーザー個人の履歴を基にレコメンドを行うため、ユーザーにハッとさせるような体験、良いUXを与えることは難しいといえます。

###最後に
レコメンドに関して説明していきましたが、いかがだったでしょうか。
最近新しい漫画を開拓したいな思って漫画レコメンドするアプリとかシステムとか組めないかなと画策していたので書いてみました。
「協調フィルタリング」と「コンテンツ単位のフィルタリング」を分けて紹介しましたが、大体の大きなサイトは両方導入されてますね。お互いの長所で欠点を補っていい感じになっているのではないでしょうか。

全くの余談ですが、Amazonと言えばえらく高評価の商品とかありますよね？
そういう商品はレビューを見てみましょう。
日本語がエキサイトしていませんか？星だけレビューが多くないですか？
そういうのを見ると不安になりますよね。そんなあなたに私からのおすすめです。
ぜひ一度サクラチェッカーにかけてみましょう。そうすれば不安も解消されるかもしれませんよ？
まぁ評価が高かろうが低かろうが買った人が満足出来れば問題なしですね！
私からのレコメンドでした。笑

それでは。
SpringBootのログ設定でapplication.ymlだけでやろうとして一部うまくいかなかった話

# 概要

小ネタですが、[SpringBoot](https://spring.io/projects/spring-boot)で、YAML形式の設定ファイルでうまくいかなかった話を書きます。

## 対象読者

- 同じようなことをして同じ目にあった人
- 2019年の時点で、SpringBoot 2.2.1などで開発している人

# SpringBootにおけるログ設定

## 背景

SpringBootでは、スムースにアプリケーションを開発できるよう、様々な工夫がなされています。[ログの設定においても、Javaの標準的なログインターフェースを上手に使えるような設定が、何もしなくても使えるように](https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-logging.html))準備されています。

## 2019年12月で、できることとできないこと

2019年12月時点の話です。この記事を読んだときに改善されていたらすみません。

筆者は、YAML形式でアプリケーションの設定ファイル(application.yml)を書くのが見やすくて好きなのですが、ログの設定に関して、エントリ執筆時点のバージョンではうまくいかない書き方がありました。

SpringBootでは、アプリケーションの設定ファイル(application.yml)に、ログに関する設定を書くことができ、外部のログライブラリのXMLファイルがなくても、ある程度コントロールすることができます。
これを用いると、通常であればlogbackやlog4jのXMLファイルを別に作成し指定しなければいけない内容について、ある程度、書かずに済む範囲があります。

例えば、アプリケーションのログレベルを決めるとき、下図のような書き方ができます。

```yaml
logging:
  level:
    root: DEBUG
```

このとき、slf4jを使って出力したログに関する制御ができ、ログレベルがDEBUGのものについて、標準出力に表示されるようになります。

SpringBootでは、ログの出力先について、標準出力以外にも、ログファイルを指定することができます。下図では、「calc.log」というファイル名を指定しています。

```yaml
logging:
  level:
    root: DEBUG
    org.springframework: DEBUG
  file: "calc.log"
```

ファイル名が指定できると、次にはファイルに関するあれこれも指定したくなります。

が、こうは書けません。(下図は動かない例。上記に加え、file:の行の後に、ファイルに関する設定を書きたいつもり。が、YAMLのフォーマットとして正しくない)

```yaml
logging:
  level:
    root: DEBUG
    org.springframework: DEBUG
  file: "calc.log"
    max-size: 1000000
```

```console
[main] ERROR com.hrkt.commandlinecalculator.CommandlineCalculatorApplication - Failed to load property source from location 'classpath:/application.yml'
java.lang.IllegalStateException: Failed to load property source from location 'classpath:/application.yml'
（中略）

        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
 in 'reader', line 13, column 3:
      level:
      ^
expected <block end>, but found '<block mapping start>'
 in 'reader', line 17, column 5:
        max-size: 1000000
        ^

        at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:572)


```

同じようなことを考えた人が、SpringBootの[Issueのところでも話をしています](https://github.com/spring-projects/spring-boot/issues/12510:)が、現時点ではできない感じです。

仕方がないので、筆者は下記のように、ファイル名のところだけ別の行にして、このエラーを回避することにしました（下図）。


```yaml
logging.file: "calc.log"
logging:
  level:
    root: DEBUG
    org.springframework: DEBUG
  file:
    max-size: 1000000
```

# おわりに

SpringBootのお便利機能のうちのログ設定部分で、筆者がYAML形式を使ってうまくいかなかった例を紹介しました。

参考までに、SpringBootの起動時のバナー表示などを抑える設定と合わせて入れると、application.ymlは下図のような形になります。

```yaml
spring:
  main:
    banner-mode: "off"
    log-startup-info: true

# logging. line is separated to 2 blocks because..
# https://github.com/spring-projects/spring-boot/issues/12510:
# https://github.com/spring-projects/spring-boot/issues/12596:

logging.file: "calc.log"
logging:
  level:
    root: DEBUG
    org.springframework: DEBUG
  file: "calc.log"
    max-size: 1000000
```
【Unity】Lightコンポーネントで色温度を使用するには

# はじめに

光の色を表現する尺度として色温度(ColorTemperature)がありますが、Lightコンポーネントで使用する際の処理が少々分かり辛かったため紹介いたします。

# 色温度を使用するには

## GraphicsSettingsの必要なコードを記述する

下記のコードを任意のスクリプトのStartイベントやEntryPointなどに記述します

```csharp
GraphicsSettings.lightsUseLinearIntensity = true;
GraphicsSettings.lightsUseColorTemperature = true;
```

## useColorTemperatureプロパティをtrueにする

色温度を使用するLightコンポーネントのuseColorTemperatureプロパティのトグルをtrueにします

![2019-12-21_04h20_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126970/ff38a174-5c94-c0d4-8b80-942095d2f2c1.png)

![2019-12-21_04h21_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126970/b888b501-4d2c-d7e3-7963-a286e95ec075.png)

# おわりに

以上2つの処理により色温度をLightコンポーネントで使用することが出来ます。
色を表現する際に色温度を使用することは稀だと思いますが、AR FoundationのLightEstimateのaverageColorTemperatureを動作させる際などに必要な処理になります。
Three.jsを用いたモデルのアニメーション切り替えを簡単にした話

この記事は、Three.js Advent Calendar 2019 20日目の記事です。

![Kapture 2019-12-21 at 2.23.03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42248/df9631d8-1051-85ec-86ac-80984292618e.gif)

## AnimationMixerが扱いづらい :smiling_imp:

Three.js内でglTFなどを読み込んでアニメーションさせる場合、AnimationMixerを使用して徐々にモーションが変わるようにするには以下のようなコードを書くことになります。

```typescript
const loader = new THREE.GLTFLoader();
loader.load('assets/zensuke.gltf', (gltf) {
  scene.add(gltf.scene)
  const mixer = new THREE.AnimationMixer(gltf.scene)
  const actionA = mixer.clipAction(gltf.animations[0])
  const actionB = mixer.clipAction(gltf.animations[1])
  let actionAWeight = 0
  let actionBWeight = 1
  mixer.play()

  function tick() {
    requestAnimationFrame(tick);
    
    // ↓適当です。AとBのWeightが入替わるような処理
    actionAWeight += 0.01
    actionBWeight -= 0.01

    // ...省略...

    actionA.setEffectiveWeight(actionAWeight)
    actionB.setEffectiveWeight(actionBWeight)
    
    renderer.render(scene, camera);
  }
})
```

各Actionのweightを調整するために冗長でとてもわかりにくいコードに仕上がりました。厳密にweightのバリデーションを追加するともっと複雑になります。


## もっと簡潔にアニメーションを切り替えたい :pray:

上のような面倒をしなくてもなめらかにモーションが切り替わってくれるだけでいいので、以下の３点だけ指定すればアニメーションが切り替わるようなツールが欲しい。。。 :cry: 

- 次のアニメーション名
- 切り替わりにかかる時間
- ループするかどうか


## また作ってみました

ということで `utsuroi` というツールを作ってみました。

- [utsuroiのリポジトリはこちら](https://github.com/sawa-zen/utsuroi)


### 簡単な使用例

```typescript
import { Manipulator } from 'utsuroi'
 
let manipulator;
 
// Load asset
var loader = new THREE.GLTFLoader();
loader.load('assets/model.gltf', (gltf) {
  scene.add(gltf.scene)

  // アニメーションの操作者を作成
  manipulator = new Manipulator(gltf.scene, gltf.animations); 

  // 初期状態として再生したいアニメーション名を指定
  manipulator.play('Rest Pose', true);
});
```

毎フレームに `update` メソッドを実行することを忘れないでください 

```typescript
function tick() {
  requestAnimationFrame(tick);
  manipulator.update(); // これをしないとweightの更新がされない
}

tick();
```

#### アニメーションを切り替える

glTFに含まれているアニメーション名を指定することで切り替えられます

```typescript
// manipulator.to('アニメーション名', 切り替えにかかる時間ms, ループするか否か);
manipulator.to('Walk', 200, true);
```

#### アニメーションを止める

```typescript
manipulator.pause();
```

ちなみにBlenderからglTF書き出した時の設定はは以下になります。NLAスタックに登録がされていないと `gltf.animations` にアニメーション情報が入ってこないので注意です。

<img width="930" alt="スクリーンショット 2019-12-21 1.37.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42248/3570e7d0-e961-c804-290d-16ed0abe31cf.png">


## まとめ

とてもシンプルになり簡単に切り替えが可能になりました。アニメーションに特にこだわりが無い方や、とりあえずアニメーションを確認したい方におすすめです。ぜひ使ってみてください :smile:
Macに(L)AMP環境を構築してlaravelを動かした時のメモ

# LAMP環境とは
Linux + Mysql + Apache + PHP の、webの一般的な構成。今回はLinux以外をインストールした。

# 参考
https://qiita.com/moroya/items/a0b7881c4b3d809c6f21
http://vdeep.net/homebrew-php-apache-mysql
https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09


# Homebrew
基本的に今回は全てhomebrewでインストールした。
入ってない方はこちらから→ https://brew.sh/

#PHPのインストール

```sh
$ brew install php
```

# Apacheのインストール

```sh
$ brew install httpd
```

```sh
$ which apachectl
/usr/local/bin/apachectl
```
このパスが返ってこれば大丈夫。

## Apacheの設定

```
$ vi /usr/local/etc/httpd/httpd.conf 
```


ポート番号を指定（80がデフォルトなのでそれに合わせる）

```httpd.conf
Listen 80
```

ホストも合わせる。（コメントアウトされていれば外す）

```httpd.conf
ServerName localhost:80 
```

ドキュメントルートを変更する。

```httpd.conf
DocumentRoot "{フォルダパス}"
```

そのすぐ下も書き換える

```httpd.conf
<Directory "{フォルダパス}">　#ドキュメントルートに合わせる。
Options FollowSymLinks
AllowOverride All　#追加
Order deny,allow
Deny from all
</Directory>
```

mod_rewriteが効くようにする。下のコメントアウトを外す。

```httpd.conf
LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so
```

`index.php`を実行できるようにする。

```httpd.conf
DirectoryIndex index.php index.html
```

phpを実行できるようにする。
`<IfModule mime_module>`内に追記。

```httpd.conf
AddType application/x-httpd-php .php
```

phpを使えるようにする。末尾に追記。
```httpd.conf
LoadModule php7_module /usr/local/Cellar/php/7.4.1/lib/httpd/modules/libphp7.so
```

# MySQLのインストール

```sh
$ brew install mysql
```

## MySQLの設定

MySQLを起動

```sh
$ mysql.server start
```

パスワードを変更

```sh
$ mysqladmin -u root password 'パスワード'
```

セキュリティ設定

```sh
$ mysql_secure_installation
```

Y/nで選択する。1つ目(パスワードチェック)、2つ目(rootのパスワード)以外はY。

```
VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No: n
```

```
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n 
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
```

# つかいかた
Apache

```sh
$ apachectl start
$ apachectl stop
$ apachectl restart
```

Mysql

```sh
mysql.server status
mysql.server start
mysql.server reload
mysql.server stop

mysql -u root -p #コンソール
```

# おまけ:nodeのインストール
laravelでjs・sassをコンパイルするために。

nodeをインストールする `nodebrew` をインストールする。

```sh
$ brew install nodebrew
$ mkdir -p ~/.nodebrew/src #行わないと次がエラーになる
$ nodebrew install-binary stable
$ nodebrew ls #インストールされているnodeを表示
$ nodebrew use {使いたいバージョン} #有効化
```

あとは、 `$HOME/.nodebrew/current/bin` にパスを通して終わり。
Chrome のコンソールで動くちょっと派手目なタイマー


console で動くちょっと派手目なタイマーを作りました

#スクリプト全体

```js

{
// 各種定数
const alertMessage = "時間です"
const htmlBody = document.getElementsByTagName('body');


// タイマーのセット

const timerSet = () => {
  let sec = prompt('計測したい秒数を半角の数字で入れてください');

  if(!isNaN(parseInt(sec, 10))) {
    countDown(sec);
  } else {
    alert('これは半角の数字ではありません。再入力してください');
    timerSet();
  }
};


// カウントダウンタイマー

const countDown = (sec) => {
  let nowDate = new Date();
  const endDate = new Date(nowDate.getTime() + sec * 1000);

  let count = sec;
  const interval = setInterval(function(){
    count--;
    console.log(count);
    nowDate = new Date();
    if(nowDate.getTime() >= endDate.getTime()){
      clearInterval(interval);
      setAlert();
    }
  }, 1000);
};


// アラート時の動作

const setAlert = () => {
  const htmlHead = document.getElementsByTagName("head");
  let createStyle = document.createElement("style");
  createStyle.setAttribute("type", "text/css");
  createStyle.innerHTML = ".vibrate { animation: vibrate .1s  infinite; } @keyframes vibrate { 0% {transform: translate(0px, 0px) rotateZ(0deg)} 25% {transform: translate(2px, 2px) rotateZ(1deg)} 50% {transform: translate(0px, 2px) rotateZ(0deg)} 75% {transform: translate(2px, 0px) rotateZ(-1deg)} 100% {transform: translate(0px, 0px) rotateZ(0deg)}}";
  htmlHead[0].appendChild(createStyle);
  htmlBody[0].classList.add('vibrate');
  setTimeout(() => {
    alert(alertMessage);
    htmlBody[0].classList.remove('vibrate');
  }, 500);
};


// タイマー関数開始

timerSet();
}
```

#解説

特に特殊なことはしてません。
ぜひ chrome の コンソールで動かしてみてください。
AWS SageMaker Studioを使ってみる

## はじめに
一週間ほど前に[JupyterじゃなくてJupyterLabを勧めるN個の理由](https://qiita.com/marutaku0131/items/9881d0430462e655a701)という記事を書きました。全然話は変わりますが、AWSの新製品発表会のre:InventというイベントでSageMaker Studioという製品が発表されました。AWSで今まで存在していたSageMakerのサービスを１つの画面で管理できることができるようです。今まで自分のローカル環境かGoogle Colaboratoryでしか機械学習をしたことのない僕ですが、このSageMaker Studioを試して見たいと思います。

## 使ってみる
使ってみます。SegeMaker Studioは現在preview releaseとなっており、近所の東京リージョンでは使用できません。使用できるのはオハイオ(us-east-2)のみになっています。

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

普通のJupyterLabって感じです。ショートカット等は僕の使う範囲（セルの移動、モード切り替え程度）では普通に使えます。
せっかくなのでSageMakerのサービスの１つであるSageMaker Autopilotを使ってみます。

### SageMaker Autopilotについて
公式によるとSageMaker Autopilotは以下のように説明されています。
> Amazon SageMaker Autopilot は、完全な制御と可視性を維持しながら、データに基づいて分類または回帰用の最適な機械学習モデルを自動的にトレーニングおよび調整します。

AutoML的なモノっぽいです。AutoMLにプラスして自動でデプロイしてくれたりするいいやつです。
僕はすぐに分析したいデータが手元にないので以下の動画を参考に試してみます。

https://www.youtube.com/watch?v=qMEtqJPhqpA

使用するデータはUCIの配布しているデータで、銀行の顧客データと定期預金を申し込んだかどうかのデータセットです。

### データのインポート
```shell
%%sh
wget -N https://archive.ics.uci.edu/ml/machine-learning-databases/00222/bank-additional.zip
unzip -o bank-additional.zip
```

### データのインポート、表示
```python
import pandas as pd

data = pd.read_csv('./bank-additional/bank-additional-full.csv', sep=';')
pd.set_option('display.max_columns', 500)     # Make sure we can see all of the columns
pd.set_option('display.max_rows', 50)         # Keep the output on one page
data.head(10)
```
今回のデータは正解ラベルがyes, noの二値になっています。それぞれの数を数えてみます

```python
data["y"].value_counts()
```

```:result
no     36548
yes     4640
```
不均衡ですね(小並感)。分析は今回の趣旨ではないので飛ばします。
この調整するところから面倒なデータもAutopilotがなんとかしてくれるみたいです。
とりあえず、trainとtestに分割して保存しておきます。

```python
import numpy as np

train_data, test_data, _ = np.split(data.sample(frac=1, random_state=123), 
                                                  [int(0.95 * len(data)), int(len(data))])  

# Save to CSV files
train_data.to_csv('automl-train.csv', index=False, header=True, sep=',') # Need to keep column names
test_data.to_csv('automl-test.csv', index=False, header=True, sep=',')

import sagemaker

prefix = 'sagemaker/DEMO-automl-dm/input'
sess   = sagemaker.Session()

uri = sess.upload_data(path="automl-train.csv", key_prefix=prefix)
print(uri)
```

### Autopilot Experimentの作成
SageMaker StudioからAutopilot Expreimentを作成します

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

項目を埋めます。最後の項目は、Noを選択するとSageMakerが自動で生成してくれたモデルを試せるnotebookを作成してくれるようです。　

`Create Experiment`を押すと自動でモデルの構築が始まります。

プロセスは大きく分けて３つの処理をしてくれます

* データの分析
* 特徴量エンジニアリング
* モデルのチューニング

結果をみた感じ、もう僕がやらずに機械に任せた方がいいのではって感じでした。技術の進歩すごい。

処理がまだ終わってないのですが、すごく眠いので今回はここまでにします。s

## 不安な点
AWSに限らずにクラウドサービス全般に言えることですが、料金体系がとてもわかりづらいです。今回のSageMaker Studioもいくらモデルの作成にかかるのかがよくわかりませんでした…
僕がボケてたとはいえ、GCPでDataProc使った時にクラスタ消し忘れて7000円吹き飛んだ恨みは消えてないぞ…

## まとめ
日本語のやってみた記事が少なかったのでやってみました。
AutoMLなめてたっていうのが正直な感想です。ただ、SageMakerの機能を統合できるという側面が強いので、SageMakerの機能をフルで使い人にはおすすめだけど単にJupyterみたいな環境が欲しい人にはどうかな？って感じでした。
obniz 1Y用ケース設計用にobniz 1Yを3Dモデル化。干渉チェック、公差のTIPS付

この記事はobniz adovent calendar 20日目の記事です。
日付をまたいでしまい申し訳ございません！
#obniz 1Y 出ましたね！

去る2019/12/18に待望のobniz最新製品obniz 1Yが発売されました！
公式ページ
<https://obniz.io/ja/products>

[@youtoy さんの記事](https://qiita.com/youtoy/items/13017a7625732a0dc27d)でその概要がわかりやすく解説されておりますのでぜひご覧ください！

![2019-12-21 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/60409def-859b-4949-7163-5a5aa05c1c15.png)

#obnizで欲しくなるのはケース！
obnizを買うと欲しくなるのが専用ケースですね。裸のままで持ち歩くよりケースに入れたほうが断然安心だったり、個性的になったりいいことずくめです。

みなさん100均プラケースやミンティアケースを使ってみたり、3Dプリンタで自作される方も多いと思います。

そうやって自作していくと、公式で公開されている外寸以外にも突起部やコネクタ部の形状や位置が知りたくなります。

そこで今回はこれから自作ケースを作るのに捗るようにobniz 1Yの3Dモデルを作成しました。

#データ概要
3Dデータを下記にUPしました。
<https://github.com/morikentech/3dmodel>

データ概要：obniz 1Yの外形を1つの塊でモデリング
データ形式：step, iges, f3d(fusion360)の3種類
データ信頼度：ノギスにて少数第一位まで実測
想定誤差：約±0.1
補足：ケース作成を目的としているため測定が難しいところは大きめにとってあります
注意：このモデルで作れば絶対に干渉しないことを保証できるものではないので、実物と見比べながら自己責任でお願いします。

![2019-12-21 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/16ce910e-dbfa-c2fe-fe8d-662713c9b166.png)

![2019-12-21 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/6486c81b-9080-aa39-93cb-639b6ed8e368.png)

#（参考）ケース作成時の干渉チェックガイド
CADを使い慣れている方はstepやigesをそのままインポートしてお使いください。

あまりCADを使い慣れていない方は無料かつ高機能な3DCAD [Fusion360](https://www.autodesk.co.jp/campaigns/design-now)の利用をおすすめします。


***データ作成～干渉チェックまで　おすすめステップ***
1. 上記のf3dファイルの寸法を参考にケースを別ファイルで大まかにつくる
2. 新たにアセンブリ用のファイルを新規作成する
3. アセンブリ用ファイルに上記のobniz 1Y本体の3D dataとケースの3D dataをD&Dする
4. アセンブリ＞ジョイントコマンドで2つのモデルの相対位置を固定する
5. ケースの3D dataをちょこちょこ直す
6. 検査＞干渉で干渉チェックをする

これで干渉がなければOKです。
さらに品質を向上させるため、以下の方法をおすすめします。

- ケースに対してobniz 1Y本体の位置をずらして干渉チェックをする。例えば、X, Y, Z方向それぞれに±0.3ずらした状態で干渉チェックをすることで全周0.2のクリアランスを確認できる。

#（参考）ばらつき・公差について
モノには加工や組み立てのばらつき（公差）が存在します。これを考慮しないとCAD上でうまくできていても実物で干渉して組み上がらないなんてことが起こったりします。
公差がどれくらいか？っていうのは加工方法や加工品のサイズ、コストのかけ方でピンキリなので意外と情報がないんですよね。。。そこで、参考までに私がちょろっと自作するときの基準を晒します。

```
基板の外形：±0.3程度
基板の部品実装高さ：±0.5程度
実装位置なら±0.1程度
3Dプリンタで作るケースの積層方向：±0.05
3Dプリンタで作るケースの左右方向：±0.3
金属加工：±0.5
```

私は普段これくらいはばらつくことを想定してものづくりをしています。
もちろん自分で加工するとこれ以上ばらつくこともあるわけで、そのときは観念して追加工しています。しかしながら、ちょっと余裕をもたせることで出来上がったものがスッと組み上がる気持ちよさを味わえるので公差を受け止められる設計をするのは非常にオススメです。

＊これだけ余裕をもてば必ず干渉しないことを保証するものではありません
＊公差は積み上がるものなので部品がいっぱいあるときは足し算しましょう

#まとめ
- obniz 1Yが出た！
- ケースを自作するのに本体の3Dモデルを作った！
- 公差を考慮して干渉チェックするとスムーズに作れる
- 投稿が遅れたのは寝落ちしたためです、すみません。。

#所感
IoTをはじめてから最初に一人で使用成功したのがobnizでした。
Wifi接続やサンプルプログラムのUXが洗練されており「本当に自分で動かせた！」という感動を味わうことができました。その感動が原動力になり電子工作を楽しめるようになったと思います。
ありがとうobniz氏！
LabVIEWで.NETのイベントコールバックを使用すると、コールバックVIがロックされてしまう場合の対処法

## 症状
.NETコントロールのイベント処理で、コールバックVIを使用すると、呼び出し元のVIが終了しているにも関わらず、コールバックVIが使用中で編集できなくなります。
イベントコールバックVIを、ライブラリに属させている場合は、ライブラリ全体がロックされてしまうので、とても作業しづらい状態になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36514/3b9679ef-b568-3c9f-a792-cfbe03a5ffb3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36514/c560eda0-7375-5b17-761c-7bea15eeabdc.png)

## 原因と対処法

LabVIEWの既知の問題リストに、リファレンスを閉じた後もコールバックVIを予約したままになることが記載されています。

対処方法には
「コールバックVIのリファレンスを閉じた後、またはコールバックVIを予約解除するために別のVIでインボークノードからGC.Collect（）を呼び出します。」
とあります。

http://www.ni.com/product-documentation/55105/en/#468139_by_Category

新規VIを作成して下記のインボークノードを配置して実行します。

アセンブリ名： mscorlib
オブジェクト名： System.GC
メソッド名： Collect
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36514/718b0ed0-4fa9-1d3b-403b-87638a254d15.png)

このVIを実行すると、コールバックVIのロックが解除されるはずです。

ちなみに、GC.Collect メソッドは強制的にガベージコレクションを実行するメソッドです。

## 自動化する

ガベージコレクションを実行すれば良いことが分かったので、終了処理に組み込んで自動化します。
実際にやってみると、VIが実行中は、当該の.NETコントロールが使用中のためなのか、開放されませんでした。
VI終了後に、手動で別のVIからガベージコレクションを実行するときちんと開放されます。これはかなりめんどくさいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36514/b37219df-3469-011c-40af-4a66963781f0.png)

少し工夫して、非同期呼び出しで別のVIからガベージコレクションが実行されるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36514/ff9011d0-ebdd-b1b4-1b21-47f4a49dccb9.png)

結果、手動の場合と同様にロックが解除されましたが、ガベージコレクション実行前にWaitを入れる必要がありました。
開発環境でのみ必要な処理なので、実行時間を気にする必要がありません。
開発環境の場合だけ実行するようにして、十分に長いWaitを設定しておくと良さそうです。

## 関連情報
LabVIEW 2019 and 2019 SP1 Known Issues
http://www.ni.com/product-documentation/55105/en/

VIを非同期で呼び出す
http://zone.ni.com/reference/ja-XX/help/371361R-0112/lvconcepts/asynchronous_vi_calls/

GC.Collect メソッド
https://docs.microsoft.com/ja-jp/dotnet/api/system.gc.collect?view=netframework-4.8
ESPNet で standalone python script で日本語 text-to-speech するメモ

https://github.com/espnet/espnet

には日本語の TTS(Transformer or Tacotron2 + parallel wavegan)の pretrained model があります.

ESPnet オフィシャルの Colab で試すことができますが, standalone で動くようにもしましょう.

スクリプトやインストール設定はここにコミットしました.

https://github.com/syoyo/espnet-tts

とりあえず推論するだけであれば, espnet 内で kaldi のビルドは不要っぽいようです.

弁護士法72条を Tacotron2 で text-to-speech しました.

https://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=324AC1000000205#764

https://clyp.it/wiybmdjk

Super coool! :tada:

ちょっとおかしいところもありますが, 追加で句点などいれればうまくいくでしょうか.

Transformer だと生成した音声は途中で結果がおかしくなりました(設定を変える必要があるか, 長いフレーズは ESPnet の Transformer では対応していないかもですね).

## TODO

* [ ] Transformer で長いフレーズにも対応する.
* [ ] ASR(音声認識)を試す
* [ ] libtorch で C++ で text-to-speech する(=> モバイルで動かしたい)
* [ ] 優秀な若人さまが, **ESPNet をお極めなされることで人類史上最速で優秀な ASR + TTS 若人さまへと昇華なされるスキーム**を確立する旅に出たい
Rails学習メモ(自分用)

from : パーフェクトRuby on Rails
https://www.amazon.co.jp/dp/B00P0UR1RU/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1


※原書がRails4基準な上、実機では試していないオプション等もあるため、自己責任で参照してくださいね。

#バリデーション一覧


| バリデーション名     | 内容                                          |
| -------------------- | --------------------------------------------- |
| validates_associated | 関連先のレコードがvalid                       |
| confirmation         | emailなど、確認フィールドと内容が一致すること |
| exclusion            | ある値でないこと                              |
| format               | あるフォーマットを満たすこと                  |
| inclusiomn           | ある値の中に含まれること                      |
| length               | ある長さを満たすこと                          |
| numericality         | 数値であること、ゼロ以上か？偶数か？も検査可能  |
| presence             | 存在すること                                  |
| absence              | 存在しないこと                                |
| uniqueness           | 値が一意であること                            |

#コールバックポイント一覧
コールバックポイント名と呼ばれるタイミングの照応表

| コールバックポイント | create | update | destroy |
| -------------------- | ------ | ------ | ------- |
| bef/aft_validation   | o      | o      | x       |
| bef/aro_save         | o      | o      | x       |
| bef/aro/aft_create   | o      | x      | x       |
| bef/aro/aft_create    | x      | o      | x       |
| bef/aro/aft_destroy  | x      | x      | o       |
| after_save           | o      | o      | x       |

 - bef ... before
 - aro ... around
 - aft ... after
コールバックが呼ばれないメソッド

- decrement
- decrement_counter
- delete
- delete_all
- increment
- increment_counter
- toggle
- touch
- update_column
- update_columns
- update_all
- update_counters

#renderメソッドのオプション

| renderオプション | 内容                                     | サンプル                                            |
| ---------------- | ---------------------------------------- | --------------------------------------------------- |
| :plain           | text/plainでテキストをそのまま表示する   | `render plain:"OK"`                                   |
| :html            | text/htmlでテキストをそのまま表示する    | `render html:"OK"`                                    |
| :body            | 生データをブラウザにそのまま帰す         | `render body:"data" `                                 |
| :nothing         | 明示的に何も表示しない                   | `render nothing:true`                                 |
| :template        | 特定のテンプレートを指定してレンダリング | `render template "submit/edit.html.erb"`              |
| :file            | 特定のファイルの内容をそのまま表示する   | `render file:'Rails.root.join('public.sample.html')' `|
| :json            | to_jsonを用いてJSONを表示する            | `render json:@submit`                                 |
| :xml             | to_xmlを用いてXMLを表示する              | `render xml:@submit`                                  |
↑2019/12/21 2:03
CakePHPのModelの自由定義メソッドについて

短いですが。

CakePHPではModelに自由なメソッドを作ることができますよね。

例えば、取得したデータをちょっといじって取得する特殊なfindなんかを定義できます。

ですが、この前遭遇したエラーがこちら。。

```sh
Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{method名}' at line 1
```

....は？

なんでsql流したことになってんの？？？

## 原因

これは気づきませんでした。

>CakePHP2系では未定義のメソッドをコールすると自動でquery()に流れる

あ。。。。（察し

また知識が一つ増えました。

因みにmethod名が間違ってただけでしたw

baserの500エラーだと早いんですがデータベースエラーになるとviewのレンダリングクッソ遅いんですよね。。。。

ありがとうございました
railsアセットプリコンパイルまとめ

<ul>
<li>javascript</li>
<li>scss</li>
</ul>

<h1>javascript</h1>

プロジェクトフォルダのapp/assets/javascript以下のファイルをすべて読み込む。
railsの初期ファイルのapplication.jsは何かというと、assets/javascript以下のファイルをすべて読み込みまとめたものにあたる。勝手にファイルをまとめてくれるので、application.jsに追加でrequireしなくてもよいのである。
しかしgemなどで追加した機能を読み込みたい場合は、application.jsにrequireする必要がある。

これはどこで使用するのかというともちろんviewである。だいたいは、layouts/application.html.erbに書かれている。<%= javascript_include_tag 'application', オプション %> のように記述すればよい。'application'の部分は、他のファイルでもよいがPATHを通す必要がある。

<h1>scss</h1>

railsでbootstrapをgemで追加する場合はcssではなく拡張子がscssのファイルになる。ここでのcssとscssの違いは記述の仕方である。cssは、javascriptと同じように//=requireのよういに記述する必要がある。また//=require_treeがあるのだがこれは、javascriptと同じですべてのファイルをまとめて読み込むというのを意味している。cssにもapplication.cssというファイルがあり、javascriptと使い方は同じである。

それに比べてscssは、@importのようにして機能をインポートする必要がある。そしてcssと違ってファイルを自動的に読み込んでくれないため、一つ一つインポートする必要がある。
例えば、A.scssというファイルとB.scssというファイルがあるとする。そしてjavascriptと同じで、application.scssというファイルがある。scssではA.scssとB.scssの両方を適用したいのならapplication.scssに、@import 'A.scss'; @import 'B.scss';と記述する必要がある。

<h1>bootstarpのテンプレートをrailsに適用するときの注意</h1>

以上の知識より、ダウンロードしたテンプレートファイルのcss部分とjs部分をそれぞれ、assets配下に配置する。
テンプレートのファイルには、bootstrap.min.cssなどのファイルが含まれているが、これはbootstrapの機能を使えるようにしますよというファイルである。なのでrails側ですでにgemでbootstrapを追加している場合は、assets配下に配置してはならない。
jquery.min.jsなどのファイルもあるがこれも同様である。

ダウンロードしたテンプレートのファイルが機能を提供するものなのか、それはrails側ですでに追加されているのかを判断してからssets配下に置くとよい

テンプレートを適用する際に必要なファイルは、index.htmlに書いてあるファイル
【Laravel】URLからパラメータを渡す方法について

#はじめに
大きく分けてルートパラメータとクエリ文字列があります
それぞれについて説明します。
#ルートパラメータを使う
まず、ルートパラメータについて説明します。
ルートパラメータは簡単な方法で
例えば、、
http://localhost:8000/hello
などでアクセス時に値（上の場合はhello）を渡す方法です
実装していく機能の概要は
URLからメッセージの文字列を取得して、コントローラーから取得して、アクセス先のビューに返します
##URLにパラメータを持たせる
URLにパラメータを設定できるようにします。

```php:routes/web.php
Route::get{'/{message}', 'UserController@index');
```

`/{message}`にアクセスすると`UserController`の`index`アクションに繋がるように設定します。
`{message}`の部分に`hello`や`welcome`など好きな言葉を記述してください

##コントローラでパラメータを取得する
まずコントローラを作成します。

```:ターミナル
$ php artisan make:controller UserController
```

ルートパラメータから値を受け取ってアクセス先のビューファイルに値を渡します。

```php:app/Http/Controllers/UserController.php
public function index($message)
{
	$data = $message;
	return view('user.index', $data);
}
```

`index($message)`で`$message`を引数にします。
そして、`$message`にルートパラメータに記述した値が入っています。
`resources/views`にある`user/index.blade.php`に`$data`を渡して表示させます。

##ビューで表示させる
コントローラーから送られた値をビューで表示させます

```html:user/index.blade.php
<p>{{message}}</p>
```

上記のコードをビューファイルに記述することで表示できます！！

これがルートパラメータを使って値を送る方法の簡単な例です

#クエリ文字列を使う
次に、クエリ文字列を使う方法について説明します
クエリ文字列は身近なところで言うと、検索機能などで使われています！
例えば、、
http://localhost:8000?serch=〇〇
などでアクセス時に値を渡す方法です

今回説明する方法は上で説明したものと同じような機能をクエリ文字列を使って実装していきます。

##ルーティングの記述
クエリ文字列を利用する時はルーティングには特別な記述はいりません
下記のような記述をしてください

```php:routes/web.php
Route::get{'/', 'UserController@index');
```

##コントローラでパラメータを拾う
URLに記述したクエリ文字列を取得し、ビューファイルに渡します。

```php:app/Http/Controllers/UserController.php
public function index(Request $request)
{
	$data = $request->message;
	return view('user.index', $data);
}
```

`Request $request`
　　$requestをRequestクラスのインスタンスとして作成しています。
`$request->message`
　　URLのに記述したクエリ文字列(`message=hello`)は
　　`$request`の中に`message`として入っています。

http://localhost:8000?message=hello
にアクセスすると表示されます。

#まとめ
基本的な２つの方法について説明しました。
今回は簡単な機能について説明しましたが、基本になります。
この説明を応用することで色々な機能が実装できるので挑戦してみてください！！

**疑問、気になるところがございましたら、質問、コメントよろしくお願いします！！！**
foursquare APIを使って2019年の行動を振り返ってみた

この記事は[アラタナアドベントカレンダー2019の21日目](https://qiita.com/advent-calendar/2019/aratana)の記事です。

![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_217773_5ef318e0-bd49-8f89-bafa-50b68dc7ffeb.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107176/9435119a-e9f0-cdf9-2ee6-9786bc4f48f3.jpeg)


# foursquare APIとは🐝
一言でまとめると、位置情報に基づいた情報を扱うことができるAPIです。
詳細は以下の公式ページで紹介されいるので、気になる方はそちらを御覧ください
https://developer.foursquare.com/

# どのようなデータが扱えるのか
[公式サイト](https://developer.foursquare.com/docs)から一部抜粋して翻訳したものが以下の表になります。

## 主な機能
機能|説明
:--:|:--:
Foursquareのグローバルデータベースへのアクセス|190か国、50の地域で利用可能な105MMを超える場所にリアルタイムでアクセスできます。
パワーアプリエクスペリエンス|カスタムAPIエンドポイントを使用して、アプリでジオタグ付け、場所の検索、場所の推奨などを強化します。
記述的な場所のプロファイル|Foursquareの消費者コミュニティが提供する70以上の会場属性と900以上のカテゴリを活用します。
豊富なユーザーコンテンツ|ユーザーが作成したヒント、好み、写真などにアクセスして、魅力的なロケーションエクスペリエンスを作成します。

## エンドポイント
エンドポイントには通常のエンドポイントとプレミアムエンドポイントの大きく2種類があります。
### 通常のエンドポイント😲
場所やお店のカテゴリーや名前といった基本的なデータにアクセスできます。
### プレミアムエンドポイント😁
その場所への評価やURL、ユーザーが作成した写真や解説、いいねなどといった多くの情報にアクセスできます。

それぞれのエンドポイントの詳細は数が多くて紹介しきれないので、[公式ページ](https://developer.foursquare.com/docs/api/endpoints)を御覧ください。



# 実際に触ってみた
今回はユーザー(自分)の過去に訪れた場所([チェックイン](https://developer.foursquare.com/docs/api/users/checkins))の情報を使って見ようと思います。


今回はエンドポイントから情報を取得するまでの工程は省略しますが、気になる方は[こちらの記事](https://syncer.jp/foursquare-api-matome)で非常に分かりやすくまとめてあるので気になる方はどうぞ。

### 立ちはだかる取得上限値の壁😾
取得できる件数の上限があったので、一回のリクエストで取得できる最大数である`250回`をパラメータで指定してあげたのですが、それでも4月から12月までの間の情報をすべて取得することができませんでした。

### 取得する期間を指定して解決😺
パラメータに`UNIX TIMESTAMP`を含めることで任意の期間からデータを取得することができたので、今回は2ヶ月ごとに区切ってチェックイン情報を取得してみました。(3ヶ月にすると上限値を超えてしまう場合があったため)

こうして取得できたレスポンスをJSONとしてダウンロードして中身を見ていくと面白い傾向が見えてきました...

## 2019年で行った場所(カテゴリ)
![Figure_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107176/29f45319-2bd7-1255-7cb0-3acb2047141e.png)

文字が小さくて見えにくいですが、一番多くチェックインしていたのが「オフィス」、次いで「コンビニ」、三番手が「食料品店(スーパー)」となりました。
全体的に飲食店が多いのが目に付きますね。。。
温泉・浴場・スパと行った娯楽施設にも多く足を運んでいたことが分かります。

## 外食のうち、和中洋の中で最も食べていたのは...
![restaurant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107176/50a1fedf-0778-8b13-4810-2053212014f7.png)


## 2019年に一番行っていたコンビニは...
![コンビニ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107176/7a0ebc18-c10b-6538-3472-63084144b925.png)

セブンが多いですね〜。

### おまけ🍜
![karamen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107176/64456ab0-4eda-e73c-4a1e-2b2163bfda32.png)

その数なんと...34回。
計測期間が4/1〜12/1の8ヶ月、日数にして約240日なので一週間に1回は食べていた計算になりますね😋


# まとめ
今回は、簡易的なグラフを出力しただけでしたが、緯度経度や時系列なんかを使うっても面白いことができそうだなぁと思いました。
こまめにチェックインしていたつもりでしたが、スルーしてしまっていた場所もまだまだあったので、来年は忘れずにチェックインしていきたいですね〜

来年も同じように振り返って比較までしてみたい！


# 参考
[Foursquare(Swarm) APIの使い方まとめ (サンプルコード付き](https://syncer.jp/foursquare-api-matome)
Raspberry PiのイメージをSDカードから書き出すまで

Raspberry Piのデータをイメージファイルとして書き出すことで、少ない容量でバックアップを生成したり、同一の環境を用意できるというメリットがある

# 環境
Raspberry Pi 
PC: Mac

# SDカードからdmg

## Raspberry Piでやること

配布する環境を用意する場合は以下の作業をする
バックアップを取るなら不要(扱いは注意)

### Wi-Fiの接続解除
無線をDisconnectしてパスワードを消す
以下でnetwork設定が表示されなければOK

```
$ cat /etc/wpa_supplicant/wpa_supplicant.conf
```

### hitsoryの消去

過去にさようならするコマンド

```bash
$ history -c
```

### ssh鍵の消去
公開鍵や秘密鍵があれば消しておく

## Macでイメージを書き出す

SDカードの名前を確認
今回は`disk3s1`

```bash
$ mount
/dev/disk3s1 on /Volumes/boot
```

`raspi.dmg`というファイルを書き出す

```bash
$ diskutil umountDisk /dev/disk3s1 # SDカードのunmount
$ sudo dd if=/dev/disk3s1 of=raspi.dmg bs=1m
$ diskutil umountDisk /dev/disk3s1 # SDカードのeject
```

unmountとejectの違いについては、https://www.junk-works.science/unmount-and-eject/#toc_id_1 を参照

# dmgからSDカード

```bash
diskutil umountDisk /dev/disk3s1
sudo dd if=raspi.dmg of=/dev/disk3s1 bs=1m
diskutil eject /dev/disk3s1
```

このSDカードをRaspberry Piにさして起動すればよい。

# 参考
http://shokai.org/blog/archives/7943
babel

# babel 困った時 Node.js environment
一番役にたったのは一番上のやつ

* **https://babeljs.io/docs/en/babel-node**

* https://jestjs.io/docs/en/getting-started#using-babel

* https://github.com/babel/example-node-server

* https://github.com/FormidableLabs/spectacle/issues/522


# 結論
```
npm install --save-dev @babel/core @babel/node
```
最初ずっと **yarn** でinstall してたんですけど, **npm** でしたら一発でした!!

# エラー内容
**Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3".**

```
Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". 
If you are sure you have a compatible version of @babel/core, 
it is likely that something in your build process is loading the wrong 
version. Inspect the stack trace of this error to look for 
the first entry that doesn't mention "@babel/core" or "babel-core" 
to see what is calling Babel. (While processing preset: 
"/Users/~/node_modules/@babel/preset-env/lib/index.js")
```
mochaにおける非同期処理の３つのテストパターン

## promiseオブジェクトをreturnするパターン 
itのコールバック関数内でpromiseオブジェクトをreturnした場合、promiseのresolve（もしくはreject）を待ちます。

```Javascript
it('asynchronous process 1', () => {
  return new Promise((resolve, reject) => {
    try {
      setInterval(() => {
        expect(1).equal(1)
        resolve();
      }, 1000)
    } catch (e) {
      reject(e);
    }
  })
})
```


## doneを使って、処理の終わりを通知するパターン
あとのパターンは、以下のような重い処理を呼び出す前提です。

```Javascript
// 1秒かかる重い処理
const heavyJob = () => {
  return new Promise(resolve => {
    setInterval(resolve, 1000);
  })
}
```

doneを引数にとり、そのdoneを使って処理の終了を伝えます。
ちなみに、doneを引数に取りながら未使用だった場合、エラーが発生します。

```Javascript
it('asynchronous process 2', (done) => {
  try {
    heavyJob().then(() => {
      expect(1).equal(1)
      done();
    }, e => done(e))
  } catch (e) { done(e) }
})
```

## async/awaitを使うパターン
環境が許す場合は、async/await を使うことができます。

```Javascript
it('asynchronous process 3', async () => {
  try {
    await heavyJob();
    expect(1).equal(1)
  } catch (e) { throw e }
})
```

## 許可されない書き方
以下の書き方をすると、例外が発生します（Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.）

```Javascript
it('anti-pattern', async (done) => {
  try {
    await heavyJob();
    expect(1).equal(1)
    done()
  } catch (e) { done(e)}
})
```


以上。
ionic リフレッシュを実装してみた ion-refresher 

# ion-refresherとは
こんな感じのツイッターとかインスタで下に引っ張って更新するやつ。
![ezgif.com-resize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368226/ac767ff4-dcb8-67ea-06a4-af671eef178f.gif)

# 使い方
- html

**注意点**：必ず、ion-content 内で使用すること。
公式ドキュメントにも以下のように書かれています。
> The refresher provides pull-to-refresh functionality on a content component.

```html:html

<ion-header>
    <ion-toolbar>
        <ion-title>
            Tab Three
        </ion-title>
    </ion-toolbar>
</ion-header>

<ion-content>
    <ion-refresher (ionRefresh)="refreshAction($event)" slot="fixed" pullMin="40" pullMax="80">
        <ion-refresher-content pullingIcon="arrow-dropdown"
                               refreshingSpinner="circles">
        </ion-refresher-content>
    </ion-refresher>
    <ion-list *ngFor="let item of items">
        <ion-item>
            <ion-label>{{item}}</ion-label>
        </ion-item>
    </ion-list>
</ion-content>

```

- typescript


```typescript:typescript

import {Component, OnInit} from '@angular/core';

@Component({
    selector: 'app-tab3',
    templateUrl: 'tab3.page.html',
    styleUrls: ['tab3.page.scss']
})
export class Tab3Page implements OnInit {
    items = [];

    ngOnInit(): void {
        this.items.push(1);
    }

    refreshAction(event) {
        setTimeout(() => {
            this.items.push(this.items.length + 1);
            event.target.complete();
        }, 500);
    }
}

```
# 参照
https://ionicframework.com/docs/api/refresher
https://ionicframework.com/docs/api/refresher-content
LeetCode: 66. Plus One

# 問題の要約
数値の一桁づつが要素として格納された配列に対し、１を足し算する問題

# 問題
[問題へのリンク](https://leetcode.com/problems/plus-one/)

# 回答　その１
愚直に一桁づつ繰上げて計算しました。

```cpp
class Solution {
    void carryUp(vector<int>::iterator curDigit, int* nextDigit) {
            *curDigit = *curDigit + *nextDigit;
            
            if(*curDigit>9) {
                *nextDigit=1;
                *curDigit = *curDigit - 10;
            } else
                *nextDigit=0;
    }
public:
    vector<int> plusOne(vector<int>& digits) {
        vector<int>::iterator curDigit=digits.end()-1;
        (*curDigit)++;
        int nextDigit=0;
        
        for(;curDigit!=digits.begin();curDigit--) {
            carryUp(curDigit,&nextDigit);
        }
        
        carryUp(curDigit,&nextDigit);
        
        if(nextDigit==1)
            curDigit=digits.insert(curDigit,1);
        
        return digits;
    }
};
```
```math
時間計算量：O(N)、空間計算量：O(1)
```
愚直に繰り上げ計算したので、スマートではないと思ったけど、提出したら Runtime=4 ms、Memory=8.7 MB 。そこそこ良い結果でした。
Rails6 マイグレーションファイルの記載ミスでマイグレートしてしまったらrollbackを使おう

# 目的

- マイグレーションファイルの記載を間違え、マイグレートしてしまった時の対処法をまとめる

# 筆者がやらかしたこと

1. マイグレーションファイルの記載をミスる。
1. その状態でマイグレートしてしまう。
1. データベースを確認したところ期待した方になっていない。
1. 現在のマイグレーションファイルを削除する。
1. 再度、マイグレーションファイルを作成し正式な記載にをした。
1. マイグレートを実行した。
1. データベースが期待したものになっていた。

# 間違えてマイグレートをしてしまった時はrollebaskをしよう

- マイグレート後にDBに異変を感じたらすぐに下記のコマンドを実行してマイグレート前の状態に戻す。

     ```terminal
     $ rails db:rolleback
     ```

- そのあとでマイグレーションファイルの記載を確認、修正を行い再度、マイグレートを行う。
ScriptableObjectをそのまま別フォルダに上書き移動するAssetPostprocessor

テラシュールさんのExcelImporter
[【Unity】Excel Importer Maker、xlsxに対応](http://tsubakit1.hateblo.jp/entry/2016/07/28/073000)
で出力したデータを、独自のフォルダにコピーしてゲーム中にロードしているのですが、
独自フォルダに自動でコピーするAssetPostprocessorを書いたのでメモしておきます。

```
using UnityEngine;
using UnityEditor;

namespace Twilight
{

	public class MasterDataOverrider : AssetPostprocessor
	{
		private const string kSrcDirectoryPath = "Assets/App/Data";
		private const string kDestDirectoryPath = "Assets/App/Resources/Data";

		/// <summary>
		/// OnPostprocessAllAssetsには効かないらしいけど一応
		/// </summary>
		/// <returns></returns>
		public override int GetPostprocessOrder()
		{
			return 100;
		}

		static void OnPostprocessAllAssets(
			string[] importedAssets,
			string[] deletedAssets,
			string[] movedAssets,
			string[] movedFromPath)
		{
			foreach (var asset in importedAssets)
			{
				if (!asset.Contains(kSrcDirectoryPath))
				{
					continue;
				}

				var loadAsset = AssetDatabase.LoadAssetAtPath<ScriptableObject>(asset);
				if (loadAsset == null)
				{
					continue;
				}

				var destFilePath = asset.Replace(kSrcDirectoryPath, kDestDirectoryPath);

				AssetDatabase.CopyAsset(asset, destFilePath);
				AssetDatabase.DeleteAsset(asset);
				AssetDatabase.Refresh();
			}
		}
	}
}
```
使う時は　kSrcDirectoryPath、kDestDirectoryPath　を、書き換えると良いかと。

※最初にAssetDatabase.CopyAsset()ではなくFile.Copy()でやろうとして時間がかかってしまった；
[アセットのコピー(AssetDatabase.CopyAsset VS File.Copy)【Unity】【エディタ拡張】](http://kan-kikuchi.hatenablog.com/entry/CopyAsset)
VSCodeで絵文字のオートコンプリート&プレビュー

# VSCode拡張「Markdown Emoji」をインストール
Extentionsから「markdown emoji」をキーワードに検索し、「Markdown Emoji」をインストールします。これにより、markdownプレビューにマークダウン絵文字がプレビュー表示されるようになります。

# VSCode拡張「:emojisense:」をインストール
Extentionsから「emojisense」をキーワードに検索し、「:emojisense:」をインストールします。これにより、後述の機能が使用できます。
なお、この機能の有効な言語を設定できるため、コード入力の妨げになることはありません。ちなみに、デフォルトの設定では以下のみが対象です。

- markdown
- text
- git-commit

# 「:emojisense:」の機能
### エディタ内で、マークアップ絵文字 のプレビュー
エディタ内で`:smile:`と入力すると、以下のようにプレビュー付きで表示されます。

```
:smile😄:
```

### unicode絵文字 の入力補完
コロン（:）を入力して、unicode絵文字 の入力補完ができます。
![emoji.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395902/a6cea8fe-41e2-9c40-c630-40319d0c5c45.gif)


### マークアップ絵文字 の入力補完
ダブルコロン（::）を入力して、github等で使われているマークアップ絵文字の入力補完ができます。

### 絵文字ピッカーの表示

コマンドパレットから`Emojisense: Pick an emoji...`コマンドを実行するか、ショートカットキーにより、絵文字ピッカーを表示できます。

ショートカットキー:

- Mac：cmd + i
- Linux：ctrl + alt + i
- Windows：ctrl + i 

![emoji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395902/2223ec9a-e305-1211-c14d-ca4a948b208e.png)

# :emojisense:拡張の設定
いずれもデフォルトでは全て有効になっています。

- emojisense.unicodeCompletionsEnabled
  - 絵文字をUnicodeとして挿入する補完を有効にする。  例）`:smile_cat:`->`😸`
- emojisense.markupCompletionsEnabled
  - マークアップ絵文字を挿入する補完を有効にする。例）`::smile_cat`->`:smile_cat:`
- emojisense.showOnColon
  - コロンを入力すると、絵文字補完を自動的に表示。
- emojisense.language
  - VSCodeの[LanguageIdentifiers](https://code.visualstudio.com/docs/languages/identifiers)ごとに有効/無効（true/false）を設定。未設定は無効。

# 最後に
この記事も、「:emojisense:」を活用して書いています。
java 変数宣言

変数宣言についても書きます。


# Javaの変数宣言(識別子)
Javaのプログラムの中で変数を使うためには
まずはじめに「変数の宣言」というものを行わなければならない。

プログラムの中で、変数を使うためには名前が付けられていなければならない。
この変数の名前のことを識別子と読んでいる。

また、変数には扱うデータの種類によって型が決まっている。この型を指定しなければならない。

## 基本
基本の書き方はこちら

```bash
型名　識別子;
```

例：年齢の場合
intで数字の型を指定
ageで変数名(識別子)を指定

```java
int age;
```

## 変数に値を代入する
Javaの場合は以下のように記号「=」（イコール）を使用して
左側に宣言した識別子で表される変数名を、右側に式を記述する。

尚、変数と「=」の間のスペースはあっても無くてもどちらでも問題ない。

```bash
変数名（識別子） = 式;
```

例:30と指定
ageという変数に、30という値を代入することを意味している。

```java
age = 30;
```

## 変数に変数値を代入する
これは、sameAgeという変数に、ageという変数に入っている値と同じものを代入することを意味している。


```java
sameAge = age;
```

# 宣言と代入をまとめて
宣言と代入をまとめて書くこともできる。

```bash
型名　識別子 = 式;
```
```java
int age = 24;
```