先般「『タスクリストをガントチャートに一発変換!』な Quick Gantt、作りました」で公開した Quick Gantt ですが、タスク一覧をタブ区切りテキストで編集できるように機能追加しました。いちおうインラインでセル毎に編集は出来てたんですが、やっぱりテキストエディタやスプレッドシートからコピペしたいことが多いので。
タスク一覧上の「TSV で編集」ボタンをクリックするとダイアログが表示されて、その中のテキストボックスで編集したりコピペできます(↓)。
先般「『タスクリストをガントチャートに一発変換!』な Quick Gantt、作りました」で公開した Quick Gantt ですが、タスク一覧をタブ区切りテキストで編集できるように機能追加しました。いちおうインラインでセル毎に編集は出来てたんですが、やっぱりテキストエディタやスプレッドシートからコピペしたいことが多いので。
タスク一覧上の「TSV で編集」ボタンをクリックするとダイアログが表示されて、その中のテキストボックスで編集したりコピペできます(↓)。
ネクタイ締めて SE らしきものをやってた頃はコードよりドキュメントのほうを山のように書いてたもんですが、限りなくプータローに近いフリーの身になってからはそんな苦行も今は昔… と言いつつ、タマに「DB の仕様書下さい」「ダンプした DDL でいいっすよね」「…え?」「え?」てなこともあります。
てな訳で、既存の MySQL データベースをソースに、よくあるテーブル定義書を生成するのが今日のお題。車輪の再発明を避けるべくグーグル先生に相談してみたら SQL::Translator という、様々な DBMS の SQL をこれまた様々なフォーマットに変換する、正にうってつけの CPAN モジュールがあったので、これを使ってみます。全体的には
という手順をとります。
まずは DB からテーブル構造をダンプ。
$ mysqldump -u hoge -pXXXXXX --no-data sample_db > sample.ddl.sql
ダンプした SQL はこんなん(↓)だとします。テーブルや列には論理名となるコメントが付けてあることを前提にしてます。
-- -- データベース: `sample_db` -- -- -------------------------------------------------------- -- -- テーブルの構造 `persons` -- CREATE TABLE IF NOT EXISTS `persons` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'レコードID', `name` varchar(50) NOT NULL COMMENT '氏名', `address` varchar(100) NOT NULL COMMENT '住所', `phone` varchar(20) NOT NULL COMMENT '電話番号', `email` varchar(50) NOT NULL COMMENT 'Eメール', `created` datetime NOT NULL COMMENT '登録日時', `modified` datetime NOT NULL COMMENT '最終更新日時', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='住所録' AUTO_INCREMENT=1 ;
で、SQL::Translator を使って SQL を XML に変換する簡単なスクリプト sql2xml.pl (↓)を作って、これを実行。
#!/usr/bin/perl use strict; use SQL::Translator; my @data = <STDIN>; my $t = SQL::Translator->new( from => 'MySQL', to => 'XML-SQLFairy', data => join("\n", @data), show_warnings => 1, ); print $t->translate;
$ perl sql2xml.pl < sample.ddl.sql > sample.ddl.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Created by SQL::Translator::Producer::XML::SQLFairy Created on Fri Jul 18 19:29:19 2014 --> <schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml"> <extra /> <tables> <table name="persons" order="1"> <extra /> <fields> <field name="id" data_type="int" size="10" is_nullable="0" is_auto_increment="1" is_primary_key="1" is_foreign_key="0" order="1"> <extra unsigned="1" /> <comments>レコードID</comments> </field> <field name="name" data_type="varchar" size="50" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="2"> <extra /> <comments>氏名</comments> </field> <field name="address" data_type="varchar" size="100" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="3"> <extra /> <comments>住所</comments> </field> <field name="phone" data_type="varchar" size="20" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="4"> <extra /> <comments>電話番号</comments> </field> <field name="email" data_type="varchar" size="50" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="5"> <extra /> <comments>Eメール</comments> </field> <field name="created" data_type="datetime" size="0" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="6"> <extra /> <comments>登録日時</comments> </field> <field name="modified" data_type="datetime" size="0" is_nullable="0" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="7"> <extra /> <comments>最終更新日時</comments> </field> </fields> <indices></indices> <constraints> <constraint name="" type="PRIMARY KEY" fields="id" reference_table="" reference_fields="" on_delete="" on_update="" match_type="" expression="" options="" deferrable="1"> <extra /> </constraint> </constraints> <comments> <comment>住所録</comment> </comments> </table> </tables> <views></views> <triggers></triggers> <procedures></procedures> </schema>
あとはこの XML をお好みにドキュメント変換するだけ。ここでは HTML に XSLT 変換します。XSL (2html.xsl)はこんな感じ(↓)。
<?xml version="1.0" encoding="utf8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://sqlfairy.sourceforge.net/sqlfairy.xml"> <xsl:output method="html" encoding="utf8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/> <xsl:template match="/s:schema"> <html lang="ja"> <head> <meta charset="utf-8"/> <title>データベース テーブル定義</title> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"/> <style> table.htable { margin: 3em auto 1em auto !important; } table.htable th { border-left: 10px solid #e5e5e5 !important; } footer { border-top: 1px solid #e5e5e5; padding: 0.5em; } </style> </head> <body> <div class="container"> <h1 class="page-header">データベース テーブル定義</h1> <xsl:apply-templates select="s:tables"/> </div> <footer class="text-center"> mariyudu.net </footer> </body> </html> </xsl:template> <xsl:template match="s:table"> <table class="table table-bordered htable"> <tbody> <tr class="active"> <th>テーブル名</th> <td><xsl:value-of select="s:comments"/></td> </tr> <tr class="active"> <th>スキーマ</th> <td><xsl:value-of select="@name"/></td> </tr> </tbody> </table> <table class="table table-condensed"> <thead> <tr> <th class="text-right">#</th> <th>論理名</th> <th>物理名</th> <th>型</th> <th class="text-right">長さ</th> <th>主キー</th> </tr> </thead> <tbody> <xsl:apply-templates select="s:fields"/> </tbody> </table> </xsl:template> <xsl:template match="s:field"> <tr> <td class="text-right"><xsl:value-of select="@order"/></td> <td><xsl:value-of select="s:comments"/></td> <td><xsl:value-of select="@name"/></td> <td><xsl:value-of select="@data_type"/></td> <td class="text-right"><xsl:if test="@size!=0"><xsl:value-of select="@size"/></xsl:if></td> <td><xsl:if test="@is_primary_key!=0"><span class="glyphicon glyphicon-ok"></span></xsl:if></td> </tr> </xsl:template> </xsl:stylesheet>
$ xsltproc -o sample.ddl.html 2html.xsl sample.ddl.xml
お疲れさま。出来たのがこんな HTML のテーブル定義書です。
ER 図とかは MySQL Workbench が便利かも。ネクタイの頃とはツール類が段違いすぐる… まぁ、ドキュメントなんて古くて新しい悩みですが、巨人の肩に乗っかってカジュアルに片付けたいもんですな。
2015-2-1 付記 : MySQL ではもっとカンタンな方法があることが判ったので続編記事を書きました → 「続・MySQL データベースからテーブル定義書を生成する」
某ブロジェクト@おしごとで比較的まとまった量の JavaScript コードを書いたんですが、これってモバイルからの利用も想定してるし圧縮・最適化をかけた方がヨイよなー、ということでその方面のツール等を物色してみました。Web I/F 上で利用できる圧縮サービスは今まで多数見かけてきましたが、サービス保守サイクルでの効率を考えるとサーバ上で CLI で使えるのが欲しい。
で、これ最強ですね。Google の closure-compiler。Java で実装されているので jar を使ってのコマンドづくりも勿論できるんですが、サービス化されてて API が用意されているのが嬉しいです。当方某プロジェクトでは Java は使っておらず、この為だけに構成サーバそれぞれで Java 環境をインスコするのもアレなので、この API を使って圧縮用 PHP スクリプトをちゃちゃっと書いてみますた。こんな感じ。
<?php define('USAGE', 'jsmin.php <JSファイル>'); define('API_URL', 'http://closure-compiler.appspot.com/compile'); if (! ($jsFile=@$argv[1]) || ! file_exists($jsFile)) { die(USAGE . "\n"); } $param = array( 'js_code' => '', 'compilation_level' => 'SIMPLE_OPTIMIZATIONS', 'output_format' => 'text', 'output_info' => 'compiled_code', ); $param['js_code'] = file_get_contents($jsFile); $options = array( 'http' => array( 'method' => 'POST', 'header' => "Content-type: application/x-www-form-urlencoded\r\n", 'content' => http_build_query($param), ) ); $result = file_get_contents(API_URL, false, stream_context_create($options)); echo $result;
使う時は
php このスクリプト.php foo.js > foo.min.js
みたいな感じで。ちなみに、今回書いた JS コードは35%サイズに圧縮されました。いいね!
上記例では変換対象 JS コードに文法誤り等無いことを前提にしてますので、エラー処理やコンパイルレベルの指定等、ちゃんとしたコマンドっぽくされたい場合はここなどを参考に、適宜いぢってみて下さい。
昔々、ある所に Mariyudu というプログラマがおりました。どうしても「でーてーえむ」というものがやりたくなって、なけなしの貯金をはたいて Mac を買ったのはもう四半世紀も前のことで御座います… という訳で、昔の情熱は何処へやら、最近はアコギやウクレレばかりの音楽生活どっぷりでアナログ老人に回帰しつつある Mariyudu@ロートルプログラマです。
もうすっかりクールジャパンを代表する勢いのボーカロイドですが、永らく制作環境が Windows 中心だった為、マカーにはいまいち敷居の高いものでした。そんな中、Mac音家(まくねや)という Mac Fan 誌記事と連動したボーカル素材音声制作プロジェクトの成果により、Mac でもボカロ制作の道が。今では初音ミクも V3 で Mac 版がリリースされてそんな不自由もなくなりつつありますけどね… さて今日は、そんなMac音家のボカロ音声「ウィスパー☆エンジェル ささやきさん」を使っての「ボカロのようなもの」を試してみた件、です。
自分がお題にしたのは、「ささやきさん、『影を慕いて』っていうちょっと古い曲があるんだけど、俺がギター弾くからさぁ、ひとつ唄ってみてくれたりしない?」とゆーものです。
Mac音家さんの一連のボカロ素材はここにもあるように、Apple 謹製の DTM アプリ GarageBand 上での利用がモデルケースになっていますが、他のアプリ上での制作も可能でむしろそちらの方が効率が良い場合もあります。自分も、このページでの説明に倣って、Studio One 2 の無料版を使ってチャレンジしてみました。これを使うと、イベント(音源による一音)のエンベロープ(音量の変化)が自在にコントロールできるので、こんなふうに先頭の摩擦音や破裂音が耳障りなイベントのアタックをいじって聴きやすくしたり(↓)
イベント同士の繋ぎ目をクロスフェードっぽく滑らかにしたり(↓)
なんてことがやり易いのです。
さて、ボーカルトラックを先に作ったので早速それに合わせてギターの録音、と行きたかった訳ですが、手持ちのオーディオ入力デバイスを何故か Studio One が認識してくれなかったので、ボーカルをサウンドファイルに書き出して、それをガレバンに取り込んでギター録音しました(↓)。
ちなみに、Studio One で使えなかったという(何でだろ?)デバイスはこれ。オーディオテクニカの USB I/F AT-9990 とステレオマイクの AT-9900 です。
で、出来たのがコレ、とw (↓)
影を慕いて (feat. ウィスパー☆エンジェルささやきさん) - YouTube
以上、バーゲンでポチッった「ささやきさん」を、ミク Mac 版が出ようと何だろうと意地でも使ってやる!! の巻でした。そろそろミク V3 買おうかな…
最近じゃウェブアプリでファイルアップロード機能なぞを実装する時は「それドラッグ&ドロップで」と当たり前のように言われてしまう訳ですが、みなさま如何お過ごしでしょうか。「連休なにそれ美味しいの?」とイタイケな Mariyudu@今日も元気でお仕事ヒャッハーです。
いやね、さっきまでその件でハマッてたんですわ。HTML5 ドラッグ&ドロップは別に初めて書く処理じゃないんだけど、IE (Win7 + IE11)だけでうまく行かないのですな。
こんな感じで画像ファイルをドロップゾーンにドラッグ&ドロップしてみると↓
無慈悲にブラウザが画像をオープンしちゃうという↓
で、コードを少しずつ削りながらネットで流通してるちゃんと動くD&Dのサンプルコードに近づけていく形で切り分けしていったら、ドロップゾーンの div のスタイルが原因でした。IE だとブロック要素にちゃんと
width: 100%; /* デフォでもいちおう指定 */
みたいに width 属性値を明示してやらないと、こんな症状が出るみたいです。あぁ、サクッと終わらして三国志のムック本読もうと思ってたのにぃ…
雪、凄いっすねー。ども、Mariyudu@野良プログラマです。確定申告未だやってません。全部雪のせいです。
零細フリーランスなどやっておると、複数取引先の掛け持ち状態ってのがフツーにある訳でして、例えばA社作業を月〜水曜日に、B社作業は木〜金にアサイン、みたいな感じで振り分けてたりします。そんな状況下だと、見積依頼が来たときに案件工数をスケジュールに落とすのが結構めんどいのですな。期間中に連休等を挟んでいると尚更です。ちょっとした日数計算処理をすりゃいいだけなので、スプレッドシートとかで自分用のスクリプトでも作ろうか… でも面倒くさい… と長らくウダウダしてたのですが、jQuery.Gantt という JavaScript 製のガントチャート作図ライブラリがカッコイイのに感動したので、これをモチベーションにひとつウェブサービスとして作ってみました。題して Quick Gantt です。
使い方はカンタン。まず、Excel みたいなグリッドにタスク名と所要日数を書き入れて(↓)、
作業開始日と、作業する曜日とかも設定します(↓)
あとはタブ「線表」をクリックすると工程表のできあがり!
データ入力用のグリッドには PQ Grid を、タイトルのフォントは Google Fonts から Faster One を、ページのカラースキームは :iroiro に決めてもらいましたw ほか、Twitter Bootstrap や jQuery を始めとしたプロダクトや数多のコードスニペットのお世話になりっぱなしです。
ざっくりと作ったばかりなので細かいところはまだまだですが、願わくば誰かのお役に立ちつつ、フィードバックでも頂ければーと。
以前書いた「apns-php のログ出力をオフにする」の続編というか姉妹編というか。
iOS デバイスへのプッシュ通知サービスを構築していると、「削除(アンインストール)されちゃれったアプリへの通知ってどうなるの?」という問題に突き当たります。で、調べてみると「プッシュ通知先デバイスに当該アプリがインストールされていない状態の場合は、通信エラーが記録されてフィードバックサービスでエラー情報を取得可能となる」とのこと。じゃぁ、そのフィードバックってどうやったら取得できるのか、ですが、これは apns-php に同梱されている ApnsPHP_Feedback クラスを使うとチョー簡単。結構重宝する機能ですが、意外に日本語情報が出回ってないようなのでコードサンプルを。
使い方は至ってシンプル。こんな感じです。
$fb = new ApnsPHP_Feedback( ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION, <証明書ファイルのパス> ); $fb->setRootCertificationAuthority(<ルート証明書ファイルのパス>); $fb->connect(); $results = $fb->receive(); forech ( $results as $result ) { // $result['deviceToken'] がエラーが発生したデバイストークンなので、 // 必要に応じてこの端末についての処理(登録ユーザから抹消する等)を行う }
うーむ、面倒くさい APNS とのやりとりをこんなにカンタンにしてくれる apns-php にもう一度大きな拍手を!!