ページ

2023年1月15日日曜日

サイトの移動

記事を移動しました。 https://www.keydrop.net Laravel9など記事は新規サイトにて記載

2017年8月20日日曜日

Mac Sierraでapache +PHP5.6をPHP7.1を利用する手順

PHP5.6=>PHP7.1をMac Sierraで利用するための手順


名称概要
実行日2017/08/20
OSMacOS Sierra
Apache2.4.27
BrewHomebrew 1.3.1


$ brew tap homebrew/dupes
$ brew tap homebrew/versions
$ brew tap homebrew/php
$ brew tap homebrew/apache
$ brew update

-- 不要なら外す
$ brew unlink php56

$ brew install php71 --with-httpd24

-- 普段CakePHPをよく利用するのでついでに手順化
$ brew install php71-intl php71-pdo-pgsql

$ sudo vi /etc/apache2/httpd.conf
-- 以下の変更--
# LoadModule php5_module libexec/apache2/libphp5.so
LoadModule php7_module /usr/local/opt/php71/libexec/apache2/libphp7.so
-------------

$ sudo vi /etc/apache2/other/php7.conf
--- 以下を追加 ---

        SetHandler application/x-httpd-php


        AddType application/x-httpd-php .php
        AddType application/x-httpd-php-source .phps

        
                DirectoryIndex index.html index.php
        

---------------

sudo mv /etc/apache2/other/php5.conf /etc/apache2/other/php5.conf.bk

-- versionチェック
$ php -v

$ sudo apachectl restart

基本はこれで行けるはずですが、自分の環境では行けず以下を対応



less /var/log/apache2/error_log
---- エラーログをチェック -----
[Sun Aug 20 20:53:25.102393 2017] [mpm_prefork:notice] [pid 86] AH00163: Apache/2.4.25 (Unix) PHP/7.1.8 configured -- resuming normal operations
[Sun Aug 20 20:53:25.102609 2017] [core:notice] [pid 86] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
---------------------------

php.iniが古いのが問題の可能性が高い
php5.6からphp7.1向けのphp.iniを公式サイトからphp-7.1.8.tar.bz2をDLし
Downloadフォルダに解凍後以下を実施


sudo mv /etc/php.ini /etc/php.ini.20170820
sudo cp Downloads/php-7.1.8/php.ini-production /etc/php.ini

これで行けました。

localhostでWebプッシュの実現(OneSignal編)

Webプッシュ技術が流行っているので試しに実装及びまとめてみました。
環境は以下に記載ですが、localhostで試験的にやってみたい人向けに書いています。
OneSignalというサービスを利用して対応してみましたが以下の理由で対応しました。他に良いものもあるかもしれないですが自分の中ではこれが一番しっくりきました。
無料で利用できる
非SSLで利用可能
Mac & Windows系の主要ブラウザ対応(iOSは非対応)
早速検証環境を羅列
環境 概要
2017/08/19日検証
プッシュサービス OneSignal
Webサーバ macOS Sierra上にapache(Apache/2.4.25)
ホスト http://localhost/~{ユーザ名}/
基本的にMacを触っていれば初期状態?で利用できるものを前提にしてみました。
http://localhost/index.htmlに実現するイメージです。

1.サイトに登録

https://onesignal.com/
に登録、登録にはメアド&パスワードでOK
GitHubとかその他でも可
登録作業は本質ではないので省略

2.新しいプロジェクトの設定(Safari編)

2-1.プロジェクト名の入力



Add a new appを押し新規作成
ここは自分で適当に決める今回は`Test’で作成
2-2.WebSite Pushを指定


何も考えずWebSiet Pushを選択
2-3.Apple Safariを指定


まずは Safariの設定をするのでApple Safariを指定
2-4.テストサイト情報を指定


必須入力が、2つで
Site Nameこれは適当で良い今回はTest1を指定
Site URLここにhttp://localhostを指定
残り2つは製品をリリースするのなら触った方が良いがとり得ず今は放置
2-5.SDKの指定


何も考えずWebsiet Pushを選択
2-6.Test実行


この画面に来ると2つのことをする必要がある
1. 承認用HTMLの作成
2. ブラウザから承認
まずは、承認用HTMLの作成から
# sudo vi /Library/WebServer/Documents/index.html.en
以下のソースを記載
<html>
<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async='async'></script>
<script>
        var OneSignal = window.OneSignal || [];
        OneSignal.push(["init", {
                appId: "{Your App IDを置き換え}",
                httpPermissionRequest: {enable: true},
                allowLocalhostAsSecureOrigin: true,
                autoRegister: true,
                notifyButton: {enable: false}
        }]);
</script>
<body>
<h1>It works!</h1>
</body>
</html>
自分で、Your App IDを置き換え部分を書き換えてください。
ブラウザから承認の実行
http://localhost/
にアクセスしてアクセスを許可をしてサイトに戻り確認作業



とここまでがSafariの設定次にその他ブラウザ対応
個人的にですが実はSafariの方が簡単でした。

3.その他ブラウザ対応

次はその他ブラウザ今回のテストはChromeで実施
この方法でFireFoxも対応可能です。
3-1.設定情報の登録



App Setting => Google Chrome and Mozilla Firefox => CONFIGUREの順番で移動



入力情報がこの場合は、https://localhostにしてMy site is not fully HTTPS設定をチェックをつけないようにして登録します。
色々試したのですがこうしないと正しく登録できない。
3-2.追加ファイルの設置
ここで認証の前に一つ対応が入ります。
index.htmlの変更は不要なのですが追加でJSファイルが1つ必要です。
# cd /Library/WebServer/Documents/
# sudo wget https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js
どうやらChromeやFireFoxだとローカル内のOneSignalSDKWorker.jsが必要みたいでこれを取って来る必要があります。
この内容の注意したいところがあります。
例えばサイトのアクセスがhttp://localhost/~{ユーザ名}/index.htmlこの場合でもOneSignalSDKWorker.jsのアクセス先はhttp://localhost/OneSignalSDKWorker.jsにする必要があるところです。
少しみてみるとCrhome用のデバッグコンソールに出て来るので失敗する場合は、エラーログをチェックしてみると良いです。

2017年6月24日土曜日

CakePHP クエリービルダー活用

CakePHP 3系を利用したQueryBuilderの活用法
複雑なSQL(Group BYを主体)を記載する方法を記載

基本的に、特別なケースでない場合初期化の処理は
省きController上で動作させる前提で記載します

Software Version
Postgres 9.6.1
CakePHP 3.3.16

まずはテーブルとデータを作成.
SQL

CREATE TABLE users (
 user_id SERIAL,
 user_name VARCHAR(256),
 role VARCHAR(32) DEFAULT 'author',
 created_date TIMESTAMP DEFAULT NOW(),
 update_date TIMESTAMP DEFAULT NOW(),
 PRIMARY KEY(user_id)
);

CREATE TABLE products (
 product_id SERIAL,
 product_name VARCHAR(256),
 price INTEGER,
 PRIMARY KEY(product_id)
);

CREATE TABLE product_orders (
 product_order_id SERIAL,
 product_id INTEGER,
 date TIMESAMP,
 user_id INTEGER,
 PRIMARY KEY(product_order_id)
);

データ用SQL

INSERT INTO users(user_name) VALUES
('User A'),
('User B');

INSERT INTO products(product_name, price) VALUES
('product A', 1000),
('product B', 100),
('product C', 200);

INSERT INTO product_orders(product_id, date, user_id) VALUES
(1, '2017/06/24 15:00:00', 1),
(1, '2017/06/24 16:00:00', 2),
(2, '2017/06/24 17:00:00', 3),
(1, '2017/06/25 15:00:00', 2),
(2, '2017/06/25 16:00:00', 3),
(2, '2017/06/26 15:00:00', 1);

基本的な共通処理

use Cake\ORM\TableRegistry;

public function initialize(array $config) {
    $this->Users = TableRegistry::get('Users');
    $this->Products = TableRegistry::get('Products');
    $this->ProductOrders = TableRegistry::get('ProductOrders');
}

1. 簡単なGroup BY

商品IDと合計件数を抽出

SQL

SELECT product_id, COUNT(product_order_id) AS total FROM product_orders GROUP BY product_id;

PHP

$productOrders = $this->ProductOrders->find();
$datas = $productOrders->select([
    'product_id',
    'total' => $productOrders->func()->count('product_order_id')
])->toArray();
  1. 少し複雑なGroup By
SELECT
    product_id, product_name, T1.total
FROM
    products
INNER JOIN (
    SELECT 
        product_id, COUNT(product_order_id) AS total
    FROM
        product_orders
    WHERE
        date >= '2016/06/25'
    GROUP BY product_order_id
) AS T1 USING(product_id)

PHP

$products = $this->Products->find();
$productOrders = $this->ProductOrders->find();
$datas = $productOrders->select([
    'product_id',
    'total' => $productOrders->func()->count('product_order_id')->where(['date' => new Time('2017-06-25')])
]);

$productsRecored = $products->join([
    'T1' => [
        'table' => $datas,
        'type' => 'INNER',
        'conditions' => 'T1.product_id = Products.product_id',
    ]
])->select([
    "product_id",
    "product_name",
    "total" => "T1.total"
])->toArray();

自分が困ったSQLを記載

2016年7月24日日曜日

Cakephp3を利用しShellでComponentを利用する.

cakephp3を利用してShellでComponentを呼び出すのが
少し面倒だったのでまとめ

src/Controller/Component/TestsComponent.php

<?php

namespace App\Controller\Component;
use Cake\Controller\Component;

class TestsComponent extends Component {

    public function test() {
        echo "OK\n";
    }
}

src/Shell/SampleShell.php

<?php
namespace App\Shell;

use Cake\Console\ConsoleOptionParser;
use Cake\Console\Shell;
use Cake\Log\Log;
use Psy\Shell as PsyShell;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use App\Controller\Component\TestsComponent;

class SampleShell extends Shell {
    public function initialize() {
        $this->Tests = new TestsComponent(new ComponentRegistry());
    }
    
    public function main() {
        $this->Tests->test();
    }
}

どうやらオートロードできないみたいなので自分でコンポーネントを初期化する必要があるみたいです。
Abstract化したりしてリフレクション的な感じで簡易化できそうな気もするのでできたら追記予定。

2016年7月2日土曜日

CentOS 7にTensorFlowをインストールする

自分メモ

以下のWindowsにVirutal Boxをインストールし実施


  • Virtual Box 5.0.22 r108108
  • 実施日:2016/06/28
  • OS CentOS-7-x86_64-Minimal-1511


普通にインストールしてネットワークが起動しない場合は以下を実施して対処

ネットーワークの起動
インストール時にonbootをonにしていない場合はこの設定が必要です。
$ nmcli c
=====
NAME UUID TYPE DEVICE
enp0s3 xxxxxxx-xxxxx-xxxx-xxxxx-xxxxxxxxxxx 802-3-ethernet enp0s3
=========

enp0s3がデバイスのID

onbootを有効にする。
$ nmcli c m enp0s3 connection.autoconnect yes

ネットワークの再起動
$ systemctl restart NetworkManager
$ systemctl restart network

IPアドレスの確認
$ ip addr


pipのインストール
$ yum install -y epel-release
$ yum install -y python-pip
$ pip install pip --upgrade

その他ライブラリのインストール
$ yum install -y python-devel python-virtualenv

TensorFlowのインストール
$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0-cp27-none-linux_x86_64.whl

TensorFlowの環境設定ファイルを設置
$ virtualenv --system-site-packages ~/tensorflow


TensorFlowの設定を呼び出し
$ source ~/tensorflow/bin/activate


$ vi test.py
========以下を貼り付け============
import tensorflow as tf
import numpy as np
==================================


$ python test.py
エラーが出なければ成功



まとめ
CentOS6系とかと比べてほとんど変わらないです。

2015年12月14日月曜日

Tensorflowで学ぶ最急降下法

Tensorflowで学ぶ最急降下法

ありきたりですが、Tensorflowの初期サンプルに掲載されている
最急降下法(train.GradientDescentOptimizer)の解説です。

最急降下法とは、ある式を作りその式に基づき
微分を行いもっとも傾きから最小の値を算出する手法です。


TensorFlowのget startedにあるIntroductionが
この最急降下法のサンプルとなります。

大まかなフローとしては
Step1.初期データ作成
Step2.予測モデルする方程式を作成
Step3.ロス関数と目標設定を作成
Step4.最適化の実行
すごくざっくりですがこの4ステップで最急降下法を実現しています。


# おまじない
import tensorflow as tf
import numpy as np

### Step1.初期データ作成 ###
# ランダムなxの値を作成
x_data = np.random.rand(100).astype("float32")
# y = 0.1x + 0.3の式に基づいた値を算出
y_data = x_data * 0.1 + 0.3

### Step2.予測モデルする方程式を作成 ###
# W 上でいう aに値する係数を初期値として-1.0~1.0の範囲でランダム生成
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
# bの値を初期値0で作成
b = tf.Variable(tf.zeros([1]))
# y = W * x + bを再現
y = W * x_data + b

### Step3.ロス関数と目標設定を作成 ###
# 予想した結果y - 実際のyのデータ二乗した結果の平均をlossと位置付ける
loss = tf.reduce_mean(tf.square(y - y_data))
# Learning Rateの指定
optimizer = tf.train.GradientDescentOptimizer(0.5)
# lossが最小化する値を目的に置く
train = optimizer.minimize(loss)

### Step4.最適化の実行 ###
# TensorFlowの実行準備
init = tf.initialize_all_variables()

# graphの準備
sess = tf.Session()
sess.run(init)

# 201回の最適化を実行
for step in xrange(201):
sess.run(train)
# 20回毎に途中の値を出力
if step % 20 == 0:
print step, sess.run(W), sess.run(b)


この流れになります。
何の脈略もないのですが自己理解のための簡易解説となります。

2015年12月1日火曜日

Apps ScriptとQiita APIを利用してGoogleスプレットシートにデータを書き込む

Qiitaの情報を自分なりに見やすくしたいと思い
APIを利用しExcelのような形で見れるようにできないかと奮闘の備忘録

まずは準備
Qiita APIを利用すために個人用認証トークンを取得設定=>アプリケーション
から設定可能で今回は読み込みだけなので「read_qiita」で発行以後のソースにこちらの認証トークンを利用します。






続いてGoogle Drive上にファイルを作成2つのファイルを作成します。

まずは、Google Drive上でスプレットシートを作成
作成自体は簡単です。
続いて名前を付けて保存します。


ここでは、ファイル名「Qiita」シート名「lists」とします。
またA列にid,B列にtitle,C列にcreate date,D列にurl,E列にtagsを入れます。 


名称はなんでも良いですが見出しとして入れてください。
シート名はApps sciprtで利用しますので注意してください。



もう一つ必要なのがスプレットシートのIDです
IDはURLから取得できます。

パターンとしては
https://docs.google.com/spreadsheets/d/{ID}/edit#gid=0&vpid=A1
上記の{ID}部分がIDとなります。


例として以下となります。



青く塗られている部分がこのシートのIDになります。
※URLにアクセスしてもすでに削除済みなので開くことができません。





ようやく本題
apps scriptを利用していきます。

apps scriptが有効でない場合は以下の処理が必要です。


新規=>その他=>アプリを追加に行きます。
検索で「apps script」と検索すると以下がでます。

こちらを追加してください。
追加ができれば前の図様ように「Google Apps Script」が表示されます。
こちらを選択しApps Scriptを新規作成します。




コードは以下です。
コード実行時にアクセス許可をもめられうので許可して実行.
ファイル名:qiita

function myFunction() {
  // スプレッドシートのID.
  var spreadsheetId = '{ID}';
 // スプレッドシートのシート名.
  var spreadsheetName = 'list';
  // Qiita APIのURL.
  var url = 'https://qiita.com/api/v2/items?page=1&per_page=100';

  // スプレッドシートにアクセス.
  var spreadsheetData = SpreadsheetApp.openById(spreadsheetId);
  // スプレッドシートのシートにアクセス.
  var sheet = spreadsheetData.getSheetByName(spreadsheetName)
  // シートのデータを取得.
  var sheetdata = sheet.getSheetValues(1, 1, sheet.getLastRow(), sheet.getLastColumn());
  // Qiita APIからデータを取得.
  var qiitas = getHttpQiitaApiRequest(url);
  
  // Qiita APIから取得したデータを列へ挿入.
  for (var n in qiitas) {
    var qitta = qiitas[n];
    var isCheck = findById(sheetdata, qitta.id);
    // 既に存在しているか確認.
    if (!isCheck) write(sheet, qitta);
    else break;
  }
  // ソートをcreate dateで降順にソート
  var sortRange = sheet.getRange(2, 1, sheet.getLastRow(), sheet.getLastColumn());
  sortRange.sort([{column: 3, ascending: false}, {column: 1, ascending: true}]);
}

/**
 * Qiita APIにアクセスしデータを取得します.
 */
function getHttpQiitaApiRequest(url) {
  // 認証トークンをセット
  var options =
      {
        'method' : 'get',
        'headers' : {
          'Authorization' : 'Bearer {認証トークン}'
        }
      };
  // HTTPリクエストを送信.
  var response = UrlFetchApp.fetch(url, options);
  // レスポンス結果を取得.
  var text = response.getContentText("UTF-8");
  // JSONパース.
  return JSON.parse(text);
}

/**
 * シートから重複するIDを検索します.
 * true: 既にIDが存在する場合. false: IDが存在しない場合.
 */
function findById(sheetdata, id) {
  for (var i in sheetdata) {
    // IDの重複チェック
    if (sheetdata[i][0] == id) return true;
  }
  return false;
}

/**
 * シートにデータを書き込みます. 
 */
function write(sheet, qitta) {
  // 最終行を取得.
  var n = sheet.getLastRow() + 1;
  // 日付の書式を変更
  var date = qitta.created_at.replace(/T/g, ' ').replace(/\+09:00/g, ' ');
  // データの書き込み
  sheet.getRange(n, 1).setValue(qitta.id);
  sheet.getRange(n, 2).setValue(qitta.title);
  sheet.getRange(n, 3).setValue(date);
  sheet.getRange(n, 4).setValue(qitta.url);
  var tag = "";
  for (var i in qitta.tags) {
    tag += qitta.tags[i].name + ",";
  }
  sheet.getRange(n, 5).setValue(tag);  
}

これを動かせば下図のような結果となります。



以上となります。
スケジューラーに組み込むと毎時更新とかが可能です。
Apps Scriptが思っている以上に色々できるので細々したの作成中です。

2015年11月25日水曜日

node.js配列データを同期処理する方法

Node.jsを利用し配列データを同期処理する方法を記載

どのように表現して良いかわからないのですが
以下のようなデータの処理です。


var datas = [{"id" : "1"}, {"id" : "2"}];

これを
id = 1
id = 2
と表示してくれるのを同期処理で書く方法です。
単純にfor文を利用すれば良いのではという話ではなく
datasはDBに保存したいデータとらえてください。

つまり実際には
INSERT INTO test(id) VALUES(1);
INSERT INTO test(id) VALUES(2);
と上記の処理をしたい比同期処理ではどちらが先にくるか不明のため
順番に配列からSQLを実行したい場合に考えた方法です。

結論的には再起処理を行います。
実際のサンプルは以下です。

function insert(datas, n, callBack) {
    if (datas.length == n) {
        if (callBack != null) callBack();
        return;
    }
    var sql = "INSERT INTO test(id) VALUES(" + datas[n].id + ")";
    console.log(sql);
    // 実際にここでSQLを実行.
    insert(datas, n + 1, callBack);
}

var datas = [{"id" : "1"}, {"id" : "2"}];
insert(datas, 0, function() {
    console.log("complite");
});
上記のようなソースになります。


INSERT INTO test(id) VALUES(1);
INSERT INTO test(id) VALUES(2);
complite
これで同期処理のようにできます。
ライブラリを使えばほかの方法もあると思うのですが
利用しない場合の考え方になります。

callback地獄感もありますが、これはこれで個人的には使い勝手が良いと思っています。

TensorFlowについて事前知識編【乱数生成】

Googleから出た話題の機械学習用のライブラリTensorFlow
こちらを触ろうと思い奮闘の備忘録

機械学習なんてやったことない+Pythonも初なのでサンプルを理解しようとするだけで必死とりあえず
ちょっとずつまとめ
※インストール手順等は公式ドキュメントとかを見て対応していただきますようにお願いいたします。
そのあたりはQiitaとかの方がすごく良いドキュメントがあります。

チュートリアルを見たらデータの生成があるのですが
まずはここからつまづいたのでまとめる

ランダムデータを作成する段階でわからなかった・・・・
じつはこの「np.float32」、「np.random.rand(2, 100)」はimport文を見たらわかるのですが
TensorFlowとは違いnumpyと言う数学用のライブラリです。
Python発なのでわからなかった(汗汗

と事前にnumpyについて少し備忘録をまとめます。

x_data = np.float32(np.random.rand(2, 100)) # Random input
これの意味ですが、0.0〜1.0までの乱数を2次元配列で100個作るという意味になります。

もっと値を小さくして2次元配列を5個つくるを実行
import numpy as np
x_data = np.float32(np.random.rand(2, 5))
print x_data
実行結果が以下

[[ 0.22113453 0.77961475 0.08531918 0.12012649 0.43397358]
[ 0.72542971 0.40160421 0.13799493 0.22445418 0.3758058 ]]


x_data = np.float32(np.random.rand(2, 5))
この中の2が次元を5が個数を表しているので変更すれば
相当な次元のデータが出来ると思います。


2次元配列で5個のランダム数が出来上がりました。
では、次に1〜10の少数にしたいであればどうするかは10をかけるだけです

import numpy as np
x_data = np.float32(np.random.rand(2, 5)) * 10
print x_data

[[ 5.39343119 5.11242962 2.86795855 7.04219055 6.99380398]
[ 1.75642431 2.2877152 8.44399357 4.74935007 5.61556864]]


高校数学の行列のイメージで0.0〜1.0の間の数字に10をかけてくれます。
ではさらに、1〜10の整数はどうするのか?
答えは以下です。

import numpy as np
x_data = np.int32(np.random.rand(2, 5) * 10)
print x_data

[[4 8 3 5 8]
[1 2 0 8 0]]


なんとなくfloat32をint32に変更すればうまいこといくと思ったのですが
先に10をかける必要がありました。 ということは0.0〜10.0までの少数も先に10をかけることも可能ということでした。
まだまだ難しい・・・

こちらを応用すれば整数は無限と出来ると思います。
64bit型がないか確認しところ以下できるみたいです。

x_data = np.int64(np.random.rand(2, 5) * 10)
x_data = np.float64(np.random.rand(2, 5) * 10)


なんかこれ以外とテストデータ作成もこれでできそうな気がしてたw
まずは基礎の基礎かと思いますが以上乱数生成に関する内容でした。

2015年9月28日月曜日

Node.jsを利用してYoutube APIにアクセスする。

Node.jsを利用したYootube APIのアクセスを行います。

まずはpackage.jsonを作りましょう。
npm利用のためです。

package.json
{
  "name": "youtube-sample",
  "version": "0.0.0",
  "description": "",
  "devDependencies": {
    "googleapis": "*"
  }
}

次にライブラリをインストールしましょう
先ほどのpackage.json同一フォルダで以下のコマンドを実行
npm install

本題の部分ですが先に認証ファイルを用意する必要があります。
ローカルで利用するためなのでoAuthの認証キーを取得する必要があります。

Google Developer Consoleへ移動し






認証情報へ移動します。

続いて「認証情報を追加」=>「サービスアカウント」を選択します。















最後に「JSON」を選択してダウンロードできるファイルを保存してpackage.jsonと同じフォルダーに置いてください












あとはただ使うだけだと10行前後で終わります。
youtube.js
var google = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var key = require('./{ファイル名をDLしたファイルに変更}.json');
var jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, ["https://www.googleapis.com/auth/youtube"], null);
jwtClient.authorize(function(err, tokens) {
    if (err) {
      console.log(err);
      return;
    }
    var youtube = google.youtube({ version: 'v3', auth: jwtClient });
    youtube.search.list({"part" : "id,snippet", q: "node.js"}, function(err2, datas) {
        if (err2) {
            console.log(err2);
            return;
        }
        for (var i = 0; i < datas.items.length; i++) console.log(datas.items[i]);
    });
});

これであとは実行だけ
node youtube.js
とすれば結果が帰ります。
Google側が用意しているライブラリを利用すれば簡単に出来るので
あとは検索の種類とかをドキュメントから探すだけで良いです。

2015年3月29日日曜日

Rを使って株価の株価チャート出す

ちょっとRを触りだし株価のチャートが出せないか検討してのでまとめました。

株価のチャート?
ぱっと思いつくのがヒゲ? ロウソク?などです。
今回の内容でこのようなイメージができます。



とある株価の3ヶ月の推移です。
出ているのは株価、25日移動平均線、75日移動平均線
出来高などが出ています。

いろいろカスタマイズできるみたいですがまだ不明な点もあるので
現在鋭意ドキュメントを解読中

では実際に必要なデータはどのようなものかというと以下のCSVになります。
"Date","Open","High","Low","Close","Volume"
2015-01-01,220,224,219,222,68000
2015-01-02,217,218,211,211,100000
2015-01-03,212,213,208,212,44000
・
・
・
2015-03-25,212,213,208,212,44000
それぞれ、ヘッダーが
日付,初値,高値,安値,終値,出来高
を示しています。

データ自体は転がっているものをまとめて持ってきたとして
使い方をご説明します。

今回は以下の要件とします。
・ヒゲグラフを出す
・過去3ヶ月の内容を出す
・25日移動平均線を出す
・75日移動平均線を出す
・出来高をだす

上記を満たす実装を作ります。
早速ソースコード
install.packages("quantmod")
library("quantmod")
loadCsv <- "~/data.csv"

data <- read.zoo(loadCsv, header=T, sep=",")

candleChart(data, theme="white",subset="last 3 months")
addSMA(25, on = 1, with.col = Close, overlay = TRUE, col = "blue")
addSMA(75, on = 1, with.col = Close, overlay = TRUE, col = "red")

このようなコードで作成ができます。
Rの中でquantmodが実際に利用するライブラリです。

5行目のデータのロードまでは、おまじないとして割愛します。

data <- read.zoo(loadCsv, header=T, sep=",")
7行目の部分で、データを入れます。
header=T
こちらでヘッダーコードを無視(だと思う)

sep=","
セパレータの指定です。
データをロードすると後は、描画だけです。


candleChart(data, theme="white",subset="last 3 months")
こちらで、ベースとなるチャートを出します。

theme="white"
初期の色が黒背景なので、白背景に変えるのをお勧めします。(黒だと個人的には見えにく)

subset="last 3 months"
3ヶ月前を出す指示を与えます。
その他の場合は「2014::2015-01」のように記述します。
2014年から2015-01までを示しているのだと思うが正直まだ自信がない
日付の指定もできるのかなど検証中

addSMA(25, on = 1, with.col = Cl, overlay = TRUE, col = "blue")
addSMA(75, on = 1, with.col = Cl, overlay = TRUE, col = "red")
最後に2つの内容ですが移動平均を出します。
移動平均といっても正確には、単純移動平均になります。
最初の数値が何日分を指定

on = 1
いまのところ用途が不明だが表示系に関するものらしい

with.col = Close
カラムの指定になります。(おそらくこれであっている)

overlay = TRUE
描画を上書きするかの指定になります。
基本TRUEになると思います。

col = "red"
移動平均線の色を指定します。

このような感じで実行すれば株のグラフがつくれます
後は、保存するなりをするだけです。

まだ不明な点はあるのですがとりあえず。
動くものはできます。

思っている以上にドキュメンがなく苦労しました。

2015年2月6日金曜日

MacにMongoDB3.0をインストール

NoSQLを本格的に勉強しようと思いとりあえずMongoDB3.0をインストール

brewで行えば簡単そうですが、まだ(2015/02/06日現在)3.0できなさそうなので
手動にてインストール

インストール先
/Users/{ユーザ名}/mongoldb
※以後のユーザ名は自分の名前に書き換えて下さい.
$ cd ~/Downloads/
# DLと解凍しインストール
$ curl -O http://downloads.mongodb.org/osx/mongodb-osx-x86_64-3.0.0-rc6.tgz
$ tar -zxvf mongodb-osx-x86_64-3.0.0-rc6.tgz
$ mkdir -p ~/mongodb
$ cp -R -n mongodb-osx-x86_64-3.0.0-rc6/ ~/mongodb

# DLしたファイルを削除
$ rm -rf mongodb-osx-x86_64-3.0.0-rc6/
$ rm mongodb-osx-x86_64-3.0.0-rc6.tgz


# パスを通します.
$ echo "export PATH=/Users/{ユーザ名}/mongodb/bin:\$PATH" >> ~/.bash_profile
$ source ~/.bash_profile
$ mkdir -p ./data/db
$ mongod --dbpath ./data/db

# ちなみに以下のようにするとログが書き込みできます。
$ sudo mongod --dbpath ./data/db --logpath /var/log/mongodb.log



以下でアクセスするととりあえず動きました。
$ mongo
==================================
MongoDB shell version: 3.0.0-rc6
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2015-02-06T01:07:50.323+0900 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2015-02-06T01:07:50.323+0900 I CONTROL  [initandlisten] 
>
==================================


launchd/launchctlを利用し、起動時に実行できるようにします。
sudo vi /Library/LaunchDaemons/org.mongodb.mongod.plist
====以下を貼り付け=============================




        Label
        org.mongodb.mongod
        RunAtLoad
        
        ProgramArguments
        
                /Users/{ユーザ名}/mongodb/bin/mongod
                --dbpath
                /Users/{ユーザ名}/mongodb/data/db
                --logpath
                /var/log/mongodb.log
        


==========================

# 権限を付与
$ sudo chown root:wheel /Library/LaunchDaemons/org.mongodb.mongod.plist
$ sudo chmod 644 /Library/LaunchDaemons/org.mongodb.mongod.plist

# サービスの実行
$ sudo launchctl load /Library/LaunchDaemons/org.mongodb.mongod.plist

# サービスの停止
# sudo launchctl unload /Library/LaunchDaemons/org.mongodb.mongod.plist

次回に触ってみようと思います。
とりあえず今日はここまで 

2014年11月9日日曜日

Node.jsでpostgres接続する

Node.jsでサーバPGをしようと思いpostgresへ接続

Node.js v0.10.26
postgres 9.3.2
上記バージョンにて確認

Node.jsはインストールされているとして以下のパッケージをnpmでインストールする必要がある。
https://github.com/brianc/node-postgres
$ npm install pg

使い方ですが、サーバで利用を想定して行うといかになります。


var pg = require('pg'); 
var http = require('http');

var conString = "postgres://postgres:@localhost:5432/postgres";
var server = http.createServer();
server.on('request', doRequest);
server.listen(1008);
function doRequest(request, response) {
    var client = new pg.Client(conString);
    client.connect(function(err) {
    if(err) {
        return console.error('could not connect to postgres', err);
    }
    client.query('SELECT NOW() AS "theTime"', function(err, result) {
        response.writeHead(200, {'Content-Type': 'text/html'});
        if(err) {
            return console.error('error running query', err);
        }
        console.log(result.rows[0].theTime);
        response.write(result.rows[0].theTime + "");
        response.end();
        client.end();
    });
});
};

コネクションの関係も見ながら確認してみたのですが。
pg.ClientはdoRequest内で行い、client.endがコネクションを閉じるメソッドのため
これが必須です。これを省くとサーバが動作する限りコネクション数が増えるので注意です。

2014年10月5日日曜日

CentOS 6.5でPHP5.3→PHP 5.4にアップグレードする

CakePHP3系を利用したいと思いPHPを5.3からアップグレード

とりあえずCentOS 6.5系でPHP5.3のインストール手順
yum install php php-mbstring php-mbstring php-pear

PHP5.3からのアップレード手順
# yum install yum-fastestmirror
# yum upgrade
# yum update
# rpm –import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
# cd /etc/yum.repos.d
# wget http://rpms.famillecollet.com/remi-enterprise.repo
# yum --enablerepo=remi update
# /etc/init.d/httpd restart

単純ですが、重要な手順です。

2014年7月20日日曜日

AWSの勉強開始

やっとこさAWSの勉強を開始するようにと思い
とりあえず本を探したらおあつらえ向きの


7/16日発売でAWSのエバンジェリストが書かれている本だったので即買い
AWSの基本的なアカウントの作り方、サーバの構築に必要な内容がまとまっていたので
これから始める人向けの本です。

≪CHAPTER 1≫システム構築をインフラから始めるには
≪CHAPTER 2≫ネットワークを構築する
≪CHAPTER 3≫サーバーを構築する
≪CHAPTER 4≫Web サーバーソフトをインストールする
≪CHAPTER 5≫ HTTP の動きを確認する
≪CHAPTER 6≫プライベートサブネットを構築する
≪CHAPTER 7≫ NAT サーバーを構築する
≪CHAPTER 8≫DB を用いたブログシステムの構築
≪CHAPTER 9≫TCP/IP による通信の仕組みを理解する
≪Appendix A≫パケットキャプチャで通信をのぞいてみる
≪Appendix B≫ネットワークの管理・運用とトラブルシューティング

これらの構成でなっているのですがネットワークを構築する部分に
IPのセグメント分けがありこちらがためになります。

よくわるWordpressのインストール等もあるのでAWSをこれからの人にオススメです

2014年7月13日日曜日

TitaniumでNow Loadingを使ったHTTPClientを実装

スマホアプリを作成する際によくある話ですが
Web通信部分(Ti.Network.createHTTPClient)を利用すると
非同期通信で画面の制御が面倒なことがあるので
これを回避する1つの方法No Loading...を実装してみました。

利用するのは、ActivityIndicatorと呼ばれるのものでこれを利用しバックグラウンドでは
Web通信を画面では、Now Loadingを表示します。

index.js
=========
function doClick(e) {
    var loading = Alloy.createController('loading',{
    handler : function(client, e){
    Ti.API.info("Received text: " + client.responseText);
         alert('success');
    }
    });
    loading.getView().open();
}
$.index.open();
=========

index.tss
=========
".container": {
backgroundColor:"white"
},
"Label": {
top: 30,
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
color: "#000"
}
=========

index.xml
=========
<Alloy>
    <Window class="container">
        <Label id="label" onClick="doClick">Hello, World</Label>
    </Window>
</Alloy>
=========


loading.js
=========
var args = arguments[0] || {};
function showIndicator(e){
    $.activityIndicator.show();
}
var url = "http://www.google.co.jp/";
var client = Ti.Network.createHTTPClient({
onload : function(e) {
    args.handler(this, e);
    $.loading.close();
    $.activityIndicator.hide();
},
onerror : function(e) {
    Ti.API.debug(e.error);
    alert('error');
    $.loading.close();
            $.activityIndicator.hide();
        },
    timeout : 5000
});
client.open("GET", url);
client.send();
=========

loading.tss
=========
".container" : {
    backgroundColor: '#999',
    opacity: 0.6,
    height:Ti.UI.FILL,
    width:Ti.UI.FILL
}
=========

loading.xml
=========
<Alloy>
    <Window class="container" onOpen="showIndicator">
        <ActivityIndicator id="activityIndicator" message="Loading..."/>
    </Window>
</Alloy>
=========

ソースはこのようになっています。
loading自体はモジュールみたいな形で利用します。
順番としては
loadingをopen->load画面を表示->HTTPリクエスト->onload処理->画面を閉じる
が流れです。

意外と簡単にでき応用も利くのでおためあれ

gitに今回作った内容を公開いたしました。
https://github.com/genyasan/ti/tree/master/loading

2014年7月6日日曜日

CentOS 6.5にgit 1.9インストール手順

今更ながらgitを行うとおもいCentOS 6.5に2014/07/06現在最新のgit 1.9.0をインストールする手順です.
使い方は追々・・・
yumで一発で終わるかと思ったらなかったのでソースから最新版をビルド

su -
$ yum install -y zlib-devel perl-devel gettext gcc curl-devel
$ wget https://git-core.googlecode.com/files/git-1.9.0.tar.gz
$ tar xfvz git-1.9.0.tar.gz
$ cd git-1.9.0
$ ./configure
$ make
$ make install
$ git --version
git version 1.9.0
$ cd ..
$ rm -rf git-1.9.0
$ rm git-1.9.0.tar.gz 

手順はシンプルなので後は使いこなすだけ
そこそこ性能がないとmakeは数分かかりました。

Titanium画面遷移のしかた

Tiを利用した画面遷移の基礎的なものを作成してみました。
TiのWindowを利用すると画面遷移が行え親から子を作るようなイメージになります。
イメージをまとめるため簡素なものを作成してみました。

ちょこっとメモをかねて作成




index index2 index3
xml
<Alloy>
  <Window class="container">
    <Label text="index2を開く" onClick="openIndex2">
  </Window>

</Alloy>
<Alloy>
  <Window class="container">
    <Label text="index2を閉じる" onClick="closeIndex2" />
    <Label text="index3を開く" onClick="openIndex3" />
  </Window>

</Alloy>
<Alloy>
  <Window class="container">
    <Label id="param1" top="30" />
    <Label text="argsをチェックする"  top="30" onClick="argsCheck" />
    <Label text="index3を閉じる" onClick="closeIndex3" />
    <Label text="index2と3を閉じる" onClick="closeIndex2and3" />
  </Window>

</Alloy>
tss
".container" : {
  backgroundColor:'#0ff',
  top: 30,
  layout: 'vertical',
}
".container" : {
  backgroundColor:'#f00',
  top: 30,
  layout: 'vertical',
}
".container" : {
  backgroundColor:'#ff0',
  top: 30,
  layout: 'vertical',
}
js
function openIndex2() {
  var index2 = Alloy.createController('index2').getView();
  index2.open();
}

$.index.open();
var args = arguments[0] || {};

function closeIndex2() {
  $.index2.close();
}

function openIndex3() {
  var index3 = Alloy.createController('index3',{window : $.index2, text : "index2の中身を入れることができる."}).getView(); 
  index3.open();
}
var args = arguments[0] || {};

function argsCheck() {
  alert("このメソッドでもargsを参照できる:" + args.text)
}
function closeIndex3() {
  $.index3.close();
}
function closeIndex2and3() {
  $.index3.close();
  args.window.close();
}

// 引数を受け取る.
$.param1.text = args.text;


少し書き方を横着しましたgitとかに上げれればよいのですが現在勉強中。

こちらのソースを実行すると画像のようになるのですが、indexはそのままindex2をopenしているだけです。
Alloyから生成するためには「Alloy.createController」こちらを利用します。
さらに注意点としてopenするときはviewである必要があるので「getView()」メソッドが必要です。

index2のところで、自分をcloseする際には「$.index2.close();」と非常にシンプルになります。
ここはおまじないでよい気がしてきました。

openIndex3の点が面白いと思えるところです。
Alloy.createControllerをする際に引数を渡すことができます。
この引数がindex3のargsに格納され利用できるのですが。

index3内の「$.param1.text = args.text;」これは理解が行いやすいのですが。
あえてalertとcloseIndex2and3をつけた部分です。

clickイベントを実行した際にもargsが生成した際に利用したインスタンスが利用可能な点です。
これにより、alertで前のwindowであるindex2のデータを見ることができます。

closeIndex2and3についても、自信と、index2を同時にcloseすることができるのです。
基本的な点かもしれないですが意外と知らないなと思いフムフムなっとく

現状ものを作るよりも、知る方が多いので苦労します。

2014年7月2日水曜日

Titanium Sqlite対応

TitaniumでDB(sqlite)対応方法です。

Alloyを用いるとmodelと呼ばれる仕組みがあるので、楽にできます.


まずはプロジェクトから右クリックで「New」→「Alloy Model」を選択。


続いて、実際のテーブルにあたるスキーマーを定義そうすると下のような「models」ディレクトリにファイルが出来上がる


とりあえずこれでDBを利用できる状態になる。
exports.definition = {
 config: {
  columns: {
      "name": "text",
      "kana": "text"
  },
  adapter: {
   type: "sql",
   collection_name: "test",
   idAttribute: "name"
  }
 },
 extendModel: function(Model) {
  _.extend(Model.prototype, {
   // extended functions and properties go here
  });

  return Model;
 },
 extendCollection: function(Collection) {
  _.extend(Collection.prototype, {
   // extended functions and properties go here
  });

  return Collection;
 }
};
1行だけ基本のソースから追加しています「idAttribute: "name"」この部分ですが
この行を加えるとPKになるようになっています。
どうやら初期状態では、columnsで定義された項目意外に「id」と呼ばれるPKが自動付与されるみたいです。
外部連携をする場合はPKがあらかじめ決まっている可能性が高いので「idAttribute」は覚えておいた方がよいです。
また、バリデータもこちらに記載できます。 簡単なバリデータであればよいのですが
複雑なものをどのように書くかわかりきっていないのでとりあえず今は放置

とりあえず、Insert,SELECT,DELETE,UPDATEを行います。

INSERT
var testModel = Alloy.createModel("test");
testModel.set({"name" : "弦也", "kana" : "ゲンヤ"});
if (testModel.isValid()) {
   testModel.save();
} else {
   alert("登録に失敗しました.");
}
これで登録ができます。
isValidはバリデーションなので初期ではただtrueが返却されるだけです。

少し応用しJSONのデータを組み合わせます。
var xhr1 = Ti.Network.createHTTPClient({
    onload: function() {
        var json = JSON.parse(this.responseText);
 var count = 0;
 for (var i in json) {
  count++;
  var testModel = Alloy.createModel("test");
  testModel.set(json[i]);
  testModel.save();
 }
    }
});
xhr1.open("GET", "http://localhost/test.json");
xhr1.send();
こういった感じが実用例かと思います。

SELECT
var testModel = Alloy.createCollection("test");
testModel.fetch();
testModel.map(function(test){
    Ti.API.info("name:" + test.get("name") + " kana:" + test.get("kana"));
});
INSERTと異なり、「Alloy.createCollection」を利用している点が注意です。
fetchでデータを取得していますがこれはすべて取得になります。
当然条件を指定したいので次のように記述
var testModel = Alloy.createCollection("test");
testModel.fetch(query : { statement: 'SELECT * FROM test WHERE name = ?', params: ['弦也'] }});
testModel.map(function(test){
    Ti.API.info("name:" + test.get("name") + " kana:" + test.get("kana"));
});
PDOなどでよく見る形式になりました。
このfetchはいろいろな形式で記載できそうなのですがまだ模索中とりあえずこれで対応できるのでよしとしています。

DELETE
var testModel = Alloy.createCollection('test');
testModel.fetch(query : { statement: 'SELECT * FROM test WHERE name = ?', params: ['弦也'] }});
while(testModel.length > 0) testModel.at(0).destroy();
少し面倒だがこのような書き方が一般的みたいです。
while文を利用するのが一番行数が少ない書き方みたいですが
その他何種類かあるのでそちらも随時試してまとめ中。

UPDATE
var testModel = Alloy.createModel("test");
testModel.set({"name" : "弦也", "kana" : "ゲンヤ"});
if (testModel.isValid()) {
   testModel.save();
} else {
   alert("更新に失敗しました.");
}
どうやら、INSERT OR UPDATEと呼ばれることを内部処理されているらしく、PKが合えば更新する使用みたいです。
これが「idAttribute」を利用している理由です。
自動で割り当てられたIDも便利ですがこれでは都合が悪いときがあるので臨機応変に対応です。
UPDATEについては、まだ調べきれていないので自信がないですがこれで動くと思います。

以上AlloyでModelsを利用するです。
もう少し応用編も今後作ってみたいと思います。