MapになっているニュースのListを日付順にソートする

要は、MapのListをMapのあるValue順にソートするということだけれど、答えはこちらのサイトで教えていただきました。

Collections.sort(maplist, new Comparator<Map<String, String>>(){
    @Override
    public int compare(Map<String, String> rec1, Map<String, String> rec2) {
        String colName1 = rec1.get("pubDate");
        String colName2 = rec2.get("pubDate");
        return colName2.compareTo(colName1);
    }    
});

mariadbのデータフォルダ移動、シンボリックリンクが一番!

以前、スティックコンピュータで、mariadbのデータフォルダをmicroSDに移したという話を書いたが、その時は、my.cnfの設定を変更したものだった。今回、VPSのmariadbはそれでも簡単にいかなかったので、新しいフォルダ/data/mysqlに、/var/lib/mysqlからのシンボリックリンクを貼ってやってみた。難なく、それだけで、全て片付いた。これが一番楽チンだ。以下の方法は、CentOS用です。他は、コマンドが違うかも。

(1)mysql (mariadb) を止める ← 重要
(3)新しいフォルダを作成しオーナーを変更する
sudo chown mysql:mysql /data/mysql
(3)新しいフォルダーに全部コピーする
sudo cp -pr /var/lib/mysql/* /data/mysql/
(4)元のフォルダーをrenameして使えなくしておく(万が一のために元に戻せるように)
(5)シンボリックリンクを貼る
sudo ln -s /data/mysql/ /var/lib/mysql
とこうなる。
lrwxrwxrwx  1 root    root      12 11月 23 15:35 2018 mysql -> /data/mysql/
(6)mysql (mariadb)  を再スタートする

Netbeansを9.0にした

何もかも、Java頼みだ。ロボット即興漫才のシステムは、ロボット内のシステム(ライブラリ)は、C++、コントローラーはHtml5(Javascript)、アプリケーションレベルは全てJavaだ。

JavaとHtml5の開発は、Netbeans頼みなのだ。久しぶりにバージョンアップした。apacheからダウンロードするようになった。これからは、apacheのnetbeansに慣れていかなければならないので、使うようにしようということだ。

https://netbeans.apache.org/download/index.html

ここからダウンロードしてインストールすれば良い。私の場合、macなので、少し違っているが、

https://github.com/carljmosca/netbeans-macos-bundle

から、ダウンロードして、スクリプトを実行すれば、今までにない、カラフルなnetbeansのスプラッシュが現れて実行される。

"Index column size too large. The maximum column size is 767 bytes." への対応

外に借りているVPSサーバーにmariadbが入れてある(何を隠そう、このサイトは、このVPSに載せてある。格安でありながら、結構使い勝手がいいので気に入っている)。ただ、バージョンは古く、MariaDB-server-5.5.60である。10.3とかにすればいいのかもしれないが、問題は、先に作ったtwitterの頻度データをそこに載せる必要があったのだが、パソコンで作ったデータベースをdumpして、移行しようとしたら、リストアするときに、

Index column size too large. The maximum column size is 767 bytes

というエラーで止まってしまうのだ。インデクスのサイズが小さすぎるらしいが、ネットにあるいろいろな対応を試みたが、うまくいかなかった。

最終的にどうしたかだけ、いや、多分この操作が良かったのだろうというところだけ書いておく。

ちなみにVPSは、CentOs の6.9あたりが入っている。これもあまり新しくない。今更、バージョンアップするのも面倒だ。

さしあたって、https://blog.cles.jp/item/9965に書いていただいているような対応をする(参考にさせていただいて感謝します)。要は、/etc/my.cnf.d/server.cnfに、

[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix = on
innodb_default_row_format = DYNAMIC # この設定が効かない場合には以下を参照

を書き加えるのだ。が、私の場合、最後の文章を入れてmariadbを再起動すると、失敗した。したがって、これは、入れることができない。ありがたいことに、それがダメな場合はというコメントで、以下のようにするといいと書いてある。

CREATE TABLE `hogetable` (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

ところが、私の場合、テーブルを作るのではなく、ダンプしたものをリストアするのであるから、このような、テーブルを作るプロセスそのものはない。ダンプの仕方を色々変えてもやってみた。indexを抜いた形でdumpして、リストアして、その後、indexを作成したりもしたが、結局同じエラーが出る。

indexを抜けば、普通にリストアできるが、index抜きで使ったら数百万のデータを検索する時間は、ほぼ使い物にならないくらいかかってしまう。

結局、150メガもあるだぷファイルの中身を見ることにした。すると、それはテキストファイルで、全てのデータベース操作がそこに書いてあるものなのだ。そして冒頭に、次のような、テーブルを作成するコマンドが書かれていた。

CREATE TABLE `tweetedwords` (  `word` varchar(200) NOT NULL,  `part` varchar(5) NOT NULL,  `frequency` int(15) NOT NULL,  KEY `twitterword` (`word`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

なんだ、そうか!という感じだ。ここに、先に教えてもらった ROW_FORMAT=DYNAMICを書き込んだら、見事、リストアできた。つまり

CREATE TABLE `tweetedwords` (  `word` varchar(200) NOT NULL,  `part` varchar(5) NOT NULL,  `frequency` int(15) NOT NULL,  KEY `twitterword` (`word`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

と変更しただけである。

良かった、良かった。

集めたツイート数が5000万を超えた

去年の12月から間を開けながらボツボツと集めたツイートが今日の時点で、55,227,803ツイート、ファイルサイズにして738Mbになった。プロセス1個で集めている。プロセスを増やしても、ツイッターアプリ経由で捉えられる(ツイッター社がサンプルで配信する)ツイートは同じものであるので無駄なのだ。地道に集めるしかない。プロセス増やしても、たくさん集まった気になるだけで中身は、単なる水ぶくれになる。プロセスは1個しかダメなのだ。

でも、まあ、ほぼ1年動かしているので、季節による言葉の方よりはだいぶなくなっていると思うので、ここらあたりで締めようと思う。ただ、ツイートの取得はずっと続けていくつもりだ。

1億を目指している。キリがいいので。

当面やりたいのは、ツイッターで使われている単語の頻度を分析することだ。

MacのphpMyAdminが動かなくなって

以前まで正常に動いていたphpMyAdminが突然動かなくなった。phpファイルを生で表示してしまう。apacheのphpモジュールの問題なのか色々探ったが、解決しない。多分、OSが更改されたための問題のようだが、わからない。

apache2から起動するのを諦めて、phpのバージョン7が入っているので、その内蔵のウェッブサーバーから起動することにした。

やり方は簡単だ。phpMyAdminのシステムは、/Library/WebServer/Documents 以下においてあるので(http://www.ibot.co.jp/wpibot/?p=131 参照)そこで、

php -S localhost:8000

と打てば、phpの内臓サーバーが起動する。ブラウザでアドレス

http://localhost:8000/phpmyadmin/

を指定すれば良い。これ以外に、macのウェブサーバーを利用するつもりがないときは、これで十分だ。

上記については、以下のサイトを参考にさせていただいた。
https://qiita.com/masahirok_jp/items/c4f0d8bb5f55a114e31b

即興漫才のボケ

今までは、間違っているのに知ったかぶりをするボケと、ツッコミが乗ってしまうボケというのを利用していたが、反対語を挟んで間違うというボケも可能だと思った。反対語を言ってしまう天丼もあっていい。

コンセプトの管理システムの必要性

今、サリーには、2万語以上のコンセプトが組み込めるようになっている。ただ、もう、絶対使わないだろうなというコンセプトも入っている。それは無駄だ。よく使いそうなコンセプトに入れ替えて、まあ、全体として2万語になればいい。

そのためのシステムなり、データベースが必要だ。潜在的可能性のあるコンセプトを貯めておいて、スコアを与え、スコアの高いものから順番に入れておくというのが望ましい。実際に、wikipediaとか、twitterで使われる頻度、辞書への掲載などの基準でスコア化する。もちろん、ライブでお客さんから出されたお題の場合は、さらにスコアを大きくすべきだろう。

Qichatでヴァーチャルなif文を作る(2)

まとめると、Qichatで、もし 変数 $varが1の時は、Aという処理、0の時はBという処理をするというのは次のように書く。

u:(実行しなさい) わかりました $exec1=1 $exec2=1
u:(e:exec1) $var==1 Aを実行します 
u:(e:exec2) $var==0 Bを実行します 

これだけのことである。もちろん、これ以外にもいろんなやり方はあるだろう。

u:(実行しなさい) わかりました $var==1 Aを実行します 
u:(実行しなさい) わかりました $var==0 Bを実行します 

これでもいいかと思ったのだが、私がやった場合は、動かなかった。このような単純化すれば動くかもしれない。ただ、ぱっと見、「実行しなさい」が二つのイベントルールにマッチするような書き方が違和感がある。

u:(実行しなさい $var==1) わかりました Aを実行します 
u:(実行しなさい $var==0) わかりました Bを実行します 

これでも動きそうな気がする。「実行しなさい」の代わりにイベントだったらどうなるだろう。

Qichatでヴァーチャルなif文を作る(1)

(※ 次の(2)で、単純に説明します、笑)

ロボットは対話で動かすというのが、私の確信だ。NAOを動かすときは、基本Qichatで書かれたtopicファイルに、自作ライブラリを起動するための独自コマンドを埋め込んで、制御する。

この間、一つのスクリプトで、即興漫才と即興謎かけのネタを切り替えるようにした。このスクリプトは、お題として識別できる語数は20000万語を超えている。それも、Qichatに書かれている。

ここで問題は、Qichatの変数 $manzai の値が1の時は、もらったお題に対して即興漫才を実行し、それが0の時は謎かけをするようにしたい。しかも、お題として認識できるのは、標準でこれまで作成したコンセプト2500語に引っかかるのか、その後拡張した18000 語の方に引っかかるのかということがある。混ぜていないのだ。

当初は以下のような書き方をしていた。

u:(お題は _~manzai_concepts です) $manzai==1 $1 ですね。少しお待ちください。 $sub_main=$1 $telepathy_to_emily="emily_getmanzai_subjects/$sub_main"
u:(お題は _~manzai_extended_concepts です) $manzai==1 $1 ですね。少しお待ちください。 $sub_main=$1 $telepathy_to_emily="emily_getmanzai_subjects/$sub_main"
u:(お題は _~manzai_concepts です) $manzai==0 $1 ですね。少しお待ちください。 $sub_main=$1 $telepathy_to_emily="emily_getnazokake_subjects/$sub_main"
u:(お題は _~manzai_extended_concepts です) $manzai==0 $1 ですね。少しお待ちください。 $sub_main=$1 $telepathy_to_emily="emily_getnazokake_subjects/$sub_main"

ロボットの出力文の中に、条件式を入れている。何が違うんだということになるかもしれない。$telepathy_to_emilyというのは、私のライブラリ ibotライブラリのコマンドであり、emilyというのは制御コンピュータの名前で、それに対してお題を送っている。コンピューターからは、作られたネタの要素がこれも、telepathyコマンド(Qichat的にいうとイベント)で返されてくるのだが。つまり、私のibotシステムでは、ロボットとロボット、ロボットとコンピュータの、ローカルネットを経由したやり取りは、すべてテレパシー機能として実現している。それで、お互いのデータのやり取りも2000バイトまでは日本語でもできるようになっているのだ。

Qichatに戻ろう。後の二つが謎かけの、標準コンセプトと拡張コンセプトの場合である。$manzai==1というのは、$manzaiの値が1の時だけ真となる。

Quichatのロボット出力に、一つでも真でないものがあると、その全体が出力しないという機能を使っている。$manzaiが1の時は、前二つのいずれかにマッチングし、そうでない時は、謎かけの後者二つのいずれかにマッチングするはずだった。

しかし、これはうまく機能しないかった。細かくは調べていないが、考えられるのは、Qichatは、マッチングしているイベント処理ステートメントのどれか一つでも偽の文があると、たとえ真の文があってもそれを実行しないということだ。

たとえば「お題はチューリップです」という拡張コンセプトのチューリップに一致した入力文(イベント文)が、漫才と謎かけで二つある。$manzaiが1ならば、漫才の文にだけ一致すると思うのだが、全体が偽となって、実行しなくなってしまうということだと思う。

そこで、まず、次のように改良した。

u:(お題は _~manzai_concepts です) $1 ですね。少しお待ちください。 $sub_main=$1 [ $getmanzai_script=1 $getnazokake_script=1 ]
u:(お題は _~manzai_extended_concepts です) $1 ですね。少しお待ちください。 $sub_main=$1 [ $getmanzai_script=1 $getnazokake_script=1]
u:(e:getmanzai_script) $manzai==1 $telepathy_to_emily="emily_getmanzai_subjects/$sub_main"
u:(e:getnazokake_script) $manzai==0 $telepathy_to_emily="emily_getnazokake_subjects/$sub_main"

ポイントは、初めのロボット出力文の最後に、オプション処理の [ ] でくくっって、のちの、テレパシー送信文の漫才と謎かけのいずれかを実行するようにしたのだ。

これでいいかと思った。実際、ちゃんと謎かけのお題を与えると、パソコンにデータを送信し、回答をもらうようになった。そして、ネタ見せもこれでやった。

ただ、問題があることもすぐにわかった。たとえば、漫才の一つ目のお題をもらって実行する。それはちゃんとやる。しかし、それを終えて、もう一つお題をもらう。すると、「〇〇ですね、少しお待ちください」と言ったあと黙ってしまうのだ。そういう時は、もう一度お題を伝えると、今度はちゃんとテレパシーを送ってパソコンからの回答ももらう。

それで、さっき原因がわかった。 [  ] のオプションオペレータを使ったからなのだ。つまり[ ]がロボットの出力に与えられると、実行するたびに、一つずつ変わるようになっている。だから、最初のお題は、漫才用に対応するが、次にまたお題をもらうと、次の謎かけの処理をしてしまうのだ。

結局!!この [ ] を外したら思う通りの処理するようになった。 [ ]を外すと、選択せずに毎回両方実行する。その先のイベント処理の出力の中に、真があろうが偽があろうが関係なしに実行するのだ。だから、$manzaiが1の時は、つねに偽になっている、謎かけは実行されずに、漫才の処理だけが実行されるのだ。

あまりに単純なことで、笑ってしまいそうなくらいだった。