Slick+PlayFramework2でデータベースアクセス

ScalaでPlayFrameworkを使う場合にDBアクセスにはanormとslickがあるようです。

slickはscalaQueryと呼ばれていたものが進化した模様。

scala2.9まではscalaQuery,それ以降はslickらしいです

http://d.hatena.ne.jp/tototoshi/20121204/1354615421

Build.scalaに必要なモジュールを書いてインストールするのが一般的らしいですが、うまくいかなかったので手動インストールで作成してみます。

slick

https://github.com/freekh/play-slick

からZIPでダウンロードし解凍

 $ cd slick-1.0.1
 $ sbt
 > compile
 > package
 $ find .|grep jar
	./slick-testkit/target/scala-2.10/slick-testkit_2.10-1.0.1.jar
	./target/root/scala-2.10/root_2.10-1.0.1.jar
	./target/scala-2.10/slick_2.10-1.0.1.jar

play-slick

プラグインなのでこちらも入れます

https://github.com/freekh/play-slick

 $ cd play-slick-master
 $ sbt
 > compile
 > package
 $ find .|grep jar
 ./target/scala-2.10/play-slick_2.10-0.3.3-SNAPSHOT.jar

プロジェクト作成

$ play new sample
			 _						_
 _ __ | | __ _ _	_| |
| '_ \| |/ _' | || |_|
|	__/|_|\____|\__ (_)
|_|						|__/

play! 2.1.2 (using Java 1.7.0_25 and Scala 2.10.0), http://www.playframework.org

The new application will be created in /Users/admin/Documents/workspace/play_sample/sample

What is the application name? [sample]
> sample

Which template do you want to use for this new application? 

	1						 - Create a simple Scala application
	2						 - Create a simple Java application

> 1
OK, application sample is created.

Have fun!

$ cd sample
$ play eclipse
$ mkdir lib
$ cp slick-1.0.1/target/scala-2.10/slick_2.10-1.0.1.jar .
$ cp play-slick-master/target/scala-2.10/play-slick_2.10-0.3.3-SNAPSHOT.jar .

Eclipse

  • eclipseの既存プロジェクトの読み込みで読み込む
  • プロジェクトのプロパティからslick_2.10-1.0.1.jar、play-slick_2.10-0.3.3-SNAPSHOT.jarのライブラリを追加

PlayFramework

http://takashima0411.hatenablog.com/entry/2012/11/28/231817

こちらの方のサンプルをそのままいただきました

Application.scala
package controllers

import play.api._
import play.api.mvc._

import play.api.data._
import play.api.data.Forms._

import models._

object Application extends Controller {

	val taskForm = Form(
		"label" -> nonEmptyText)

	def index = Action {
		Redirect(routes.Application.tasks)
	}

	def tasks = Action {
		Ok(views.html.index(Tasks.all(), taskForm))
	}

	def newTask = Action { implicit request =>
		taskForm.bindFromRequest.fold(
			errors => BadRequest(views.html.index(Tasks.all(), errors)),
			label => {
				Tasks.create(label)
				Redirect(routes.Application.tasks)
			})
	}

	def deleteTask(id: Long) = Action {
		Tasks.delete(id)
		Redirect(routes.Application.tasks)
	}

}
Task.scala
package models

import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession

case class Task(id: Long, label: String)

object Tasks extends Table[Task]("TASK") {

	def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
	def label = column[String]("LABEL", O.NotNull)
	def * = id ~ label <> (Task, Task.unapply _)
	def ins = label returning id

	def all(): List[Task] = connectDB {
		Query(Tasks).sortBy(_.id).list
	}

	def create(label: String) = connectDB {
		Tasks.ins.insert(label)
	}

	def delete(id: Long) = connectDB {
		Tasks.where(_.id === id).delete
	}

	def connectDB[Any](f: => Any): Any = {
		Database.forURL("jdbc:h2:mem:play", driver = "org.h2.Driver") withSession {
			f
		}
	}

}
Global.scala
import play.api._
import models._
import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession

import models._
import java.sql.{Date,Time,Timestamp}

object Global extends GlobalSettings {

	override def onStart(app: Application) {
		Logger.info("Application has started")

		Database.forURL("jdbc:h2:mem:play", driver = "org.h2.Driver") withSession {

			Tasks.ddl.create

		}

	}

	override def onStop(app: Application) {
		Logger.info("Application shutdown...")
	}

}
index.scala.html

@(tasks: List[Task], taskForm: Form[String])

@import helper._


		
		

@tasks.size task(s)

    @tasks.map { task =>
  • @task.label @form(routes.Application.deleteTask(task.id)) { }
  • }

Add a new task

@form(routes.Application.newTask) { @inputText(taskForm("label")) }
routes
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
GET		 /													 controllers.Application.index
GET		 /index											controllers.Application.index
GET		 /tasks											controllers.Application.tasks
GET		 /newTask										controllers.Application.newTask
GET		 /deleteTask/:id								 controllers.Application.deleteTask(id:Long)

# Map static resources from the /public folder to the /assets URL path
GET		 /assets/*file							 controllers.Assets.at(path="/public", file)
application.conf
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"


slick.default="models.*"

# Evolutions
# ~~~~~
# You can disable evolutions if needed
evolutionplugin=disabled

これでとりあえず動きます

Eclipse4.3 Kepler で逆コンパイル

eclipseの逆コンパイルのjd-clipseですが、いつの頃からかデフォルトで動かなくなってしまいました。

以下の方法で動くようになりました

  • MacOS 10.8
  • Eclipse 4.3

Jd-clipseよりこちらが良さそうです

Mchr3k – JDEclipse-Realign

http://mchr3k.github.com/jdeclipse-realign/

1.EclipseについてーInstallation DetailsからJD-Eclipseをアンインストール

2.HelpーInstall New Softwareでhttp://mchr3k-eclipse.appspot.com/からインストール(Java Decomplier Eclipse PluginだけでOK)

3.Eclipse環境設定ーGeneralーEditorsーFileAssociationsでclassとclass witiout sourceにClassFileEditorを追加しdefault にする

これでOKのはず

JavaScriptでコールバック関数に引数をとりAjaxでデータを取得してみる

JavaScriptでコールバック関数の実装ですが、いろいろなところで書かれているのですがちょっとよくわからなかったので試してみました。

a.html


	  
	

これで

	a=d,b=c

と表示されます。

ここでjQueryを使ってAjaxでデータを取得してみます。

b.txt

test

これを用意しておきhttpで取得してみます


    


a=test,b=d

うまくとれましたが、これでいいのかどうか。

統計ソフトRを使用して株価チャートを簡単に作成(4)

ようやくチャートが描ける準備が整ったので分析に入ります。

まずは自分で作成した計算式で作成した値をチャートに書いてみます

library(RFinanceYJ)
library(quantmod)
stockCode<-"6758.t"
today<-Sys.Date()
sinceDate<-today-100 #100日分
stockData<-quoteStockTsData(stockCode,since=sinceDate)
colnames(stockData)<-c("Date","Open","High","Low","Close","Volume")
stockData.zoo<-read.zoo(stockData)
candleChart(stockData.zoo,theme="white")
#とりあえず平均値をチャート領域に書いてみる
mydata<-data.frame(Date=stockData$Date,Close=mean(stockData$Close))
mydata.zoo<-read.zoo(mydata)
addTA(mydata.zoo,on=1,col="red")

統計ソフトRを使用して株価チャートを簡単に作成(3)

データをとれるようになったのでチャートを書いてみる

library(quantmod)
library(RFinanceYJ)
stockCode<-"6758.t"
today<-Sys.Date()
dataTerm<-100 # 100日分取得
sinceDate<-today-dataTerm
colnames(stockData)<-c("Date","Open","High","Low","Close","Volume")
stockData.zoo<-read.zoo(stockData)
candleChart(stockData.zoo,theme="white")

ファイルにする場合はこちら

library(quantmod)
library(RFinanceYJ)
stockCode<-"6758.t"
today<-Sys.Date()
dataTerm<-100 # 100日分取得
sinceDate<-today-dataTerm
colnames(stockData)<-c("Date","Open","High","Low","Close","Volume")
stockData.zoo<-read.zoo(stockData)
pngDir<-"png/"
fileName<-paste(pngDir,stockCode,".png",sep="")
png(fileName,width=600,height=400)
candleChart(stockData.zoo,theme="white")
dev.off()

これをシェルでまわせば複数銘柄とれます

  • chart.R
stockCode<-commandArgs()[5]
library(quantmod)
library(RFinanceYJ)
today<-Sys.Date()
dataTerm<-100 # 100日分取得
sinceDate<-today-dataTerm
colnames(stockData)<-c("Date","Open","High","Low","Close","Volume")
stockData.zoo<-read.zoo(stockData)
pngDir<-"png/"
fileName<-paste(pngDir,stockCode,".png",sep="")
png(fileName,width=600,height=400)
candleChart(stockData.zoo,theme="white")
dev.off()
  • chart.sh
#!/bin/sh
codes="
6758
9501
9433
"
for code in $codes;do
R --vanilla --slave --args ${code}.t <	chart.R
done

PlayFramework2.1で既存のMySQLにつないでみる

ちょっと悩んだのでメモ

PlayFrameworkで既存のMySQLにつなぐためには

テーブルはこれ

use sampled
;
create table sample(
id integer,
name varchar(32)
)
;
create unique index idx_sampleTable on sampleTable(id)
;

まずモデル

package models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import play.db.ebean.model;

@Entity
@Table(name="sample")
public class Sample extends Model
{
	@Column(name="id")
	@Id
	public integer id;

	@Column(name="name")
	public String name;

	public String toString(){
		return id+","+name;
	}
}

application.conf

..
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://dbserver/sampledb"
db.default.user=root
db.default.password=password

evolutionplugin=disabled


ebean.default="models.*"
..

これを使って、ViewとControllerにつなげれやればおっけー

統計ソフトRを使用して株価チャートを簡単に作成(2)

RFinanceYJパッケージですがどうやらYahoo側の変更のせいでうまく動かないみたいです

> stockCode<-"6758.t"
> quoteStockTsData(stockCode)
 以下にエラー as.POSIXlt.character(x, tz, ...) : 
	character string is not in a standard unambiguous format

いろいろ調べてみたところ、どうやら日付部分が日本語のためうまく処理できていないようでした。

ちょっといじったソースはこれ


quoteStockTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
	function.stock <- function(quote.table.item){
		if( xmlSize(quote.table.item) < 5) return(NULL)
		d <- convertToDate(xmlValue(quote.table.item[[1]]),time.interval)
		o <- as.number(xmlValue(quote.table.item[[2]]))
		h <- as.number(xmlValue(quote.table.item[[3]]))
		l <- as.number(xmlValue(quote.table.item[[4]]))
		c <- as.number(xmlValue(quote.table.item[[5]]))
		v <- ifelse(xmlSize(quote.table.item) >= 6,as.number(xmlValue(quote.table.item[[6]])),0)
		return(data.frame(date=d,open=o,height=h,low=l,close=c,volume=v))
	}
	return(quoteTsData(x,function.stock,since,start.num,date.end,time.interval))
}
quoteFundTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
	function.fund <- function(quote.table.item){
		d <- convertToDate(xmlValue(quote.table.item[[1]]),time.interval)
		if(time.interval=='monthly'){
			d <- endOfMonth(d)
		}
		c <- as.number(xmlValue(quote.table.item[[2]]))
		v <- as.number(xmlValue(quote.table.item[[3]]))
		return(data.frame(date=d,constant.value=c,NAV=v))
	}
	return(quoteTsData(x,function.fund,since,start.num,date.end,time.interval))
}
quoteFXTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
	function.fx <- function(quote.table.item){
		d <- convertToDate(xmlValue(quote.table.item[[1]]),time.interval)
		o <- as.number(xmlValue(quote.table.item[[2]]))
		h <- as.number(xmlValue(quote.table.item[[3]]))
		l <- as.number(xmlValue(quote.table.item[[4]]))
		c <- as.number(xmlValue(quote.table.item[[5]]))
		return(data.frame(date=d,open=o,height=h,low=l,close=c))
	}
	return(quoteTsData(x,function.fx,since,start.num,date.end,time.interval))
}


quoteTsData <- function(x,function.financialproduct,since,start.num,date.end,time.interval){
	r <- NULL
	result.num <- 51
	quote.table.list <- list(NULL)
	quote.table <- NULL
	financial.data <- data.frame(NULL)
	start <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&c=\\1&a=\\2&b=\\3",since))
	end	 <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&f=\\1&d=\\2&e=\\3",date.end))

	if(!any(time.interval==c('daily','weekly','monthly'))) stop("Invalid time.interval value")
	
	while( result.num >= 51 ){
		quote.url <- paste('http://table.yahoo.co.jp/t?s=',x,start,end,'&y=',start.num,'&g=',substr(time.interval,1,1),sep="")
		try( r <- xmlRoot(htmlTreeParse(quote.url,encoding="EUC-JP",error=xmlErrorCumulator(immediate=F))), TRUE)
		if( is.null(r) ) stop(paste("Can not access :", quote.url))

		try( quote.table <- r[[2]][[1]][[1]][[13]][[1]][[1]][[1]][[4]][[1]][[1]][[1]], TRUE )
		if( is.null(quote.table) ) stop(paste("Can not quote :", x))

		size <- xmlSize(quote.table) 

		for(i in 2:size){
			financial.data <- rbind(financial.data,function.financialproduct(quote.table[[i]]))
		}	 
					
		result.num <- xmlSize(quote.table)
		start.num <- start.num + 50
		Sys.sleep(1)
	}
	financial.data <- financial.data[order(financial.data$date),]
	return(financial.data)
}

#convert string formart date to POSIXct object
convertToDate <- function(date.string,time.interval)
{
	#date.string <- iconv(date.string,"EUC-JP","UTF-8","")
	date.string<-gsub("日","",gsub("[年月]","-",date.string))
	#data format is different between monthly and dialy or weekly
	if(any(time.interval==c('daily','weekly'))){
		result <- gsub("^([0-9]{4})([^0-9]+)([0-9]{1,2})([^0-9]+)([0-9]{1,2})([^0-9]+)","\\1-\\3-\\5",date.string)
	}else if(time.interval=='monthly'){
		result <- gsub("^([0-9]{4})([^0-9]+)([0-9]{1,2})([^0-9]+)","\\1-\\3-01",date.string)
	}
	return(as.POSIXct(result))
}

#convert string to number.
as.number <- function(string)
{
	return(as.double(as.character(gsub("[^0-9.]", "",string))))
}
#return end of month date.
endOfMonth <- function(date.obj)
{
	startOfMonth		 <- as.Date(format(date.obj,"%Y%m01"),"%Y%m%d")
	startOfNextMonth <- as.Date(format(startOfMonth+31,"%Y%m01"),"%Y%m%d")
	return(startOfNextMonth-1)
}


これをRFinanceYJパッケージに続けて呼べばデータが取得できました

> 
> quoteStockTsData("6758.t")
				 date open height	low close	 volume
62 2013-03-25 1694	 1729 1662	1712 34382500
61 2013-03-26 1682	 1688 1660	1666 26291500
60 2013-03-27 1666	 1691 1663	1675 18503100
59 2013-03-28 1663	 1666 1587	1625 33812600
...

統計ソフトRを使用して株価チャートを簡単に作成(1)

統計ソフトのRには様々なパッケージがありExcelなどでは結構手間がかかることでもあっという間にできる場合があります

今回は株価チャートを作成してみました

まずはRのインストールから

環境

  • mac OS10.8.3
  • R 3.0.1

http://cran.r-project.org/

  1. こちらからMacOX用のものをダウンロード。(以前は32ビット、64ビットと分かれていたが統合されたみたい)
  2. インストールして起動
  3. チャート用のパッケージとデータダウンロード用のパッケージを入れる
> #プロキシサーバ越えの場合はこれを入れる
> Sys.setenv(http_proxy="http://proxyserver:port")
> 
> install.packages("quantmod")
> install.packages("RFinanceYJ")
> library(RFinanceYJ)
 要求されたパッケージ XML をロード中です 
> library(quantmod)
 要求されたパッケージ Defaults をロード中です 
 要求されたパッケージ xts をロード中です 
 要求されたパッケージ zoo をロード中です 

 次のパッケージを付け加えます: ‘zoo’ 

 以下のオブジェクトはマスクされています (from ‘package:base’) : 

		 as.Date, as.Date.numeric 

 要求されたパッケージ TTR をロード中です 
Version 0.4-0 included new data defaults. See ?getSymbols.
> stockData<-quoteStockTsData("6758.t")
 以下にエラー order(financial.data$date) :	引数 1 がベクトルではありません 

なぜかエラー。。。