寝坊検知&遅刻の言い訳提案システム #2
お疲れ様です。高橋です。
昨日作った遅刻の言い訳提案システムですが、Tweetの採取(search)と言い訳の提案(reply)、提案内容のA/Bテスト、寝坊した人の反応(ネガ/ポジ)を踏まえ、色々な知見を得ることが出来ました。
わかった事
- 土日の寝坊者は、遊び関連イベントへの遅刻が多い
- 個人に対するピンポイントなReplyなので、面白系の提案が来たらリツイートする率が高い
- いかにも自動的に生成した風なReplyのほうがポジ反応
- 10分前以上の「寝坊した」に提案するとネガ反応
- まるっきり的外れな提案するとネガ反応
- ドンピシャな提案するとポジ反応
対応した事
- 土日は完全対象外としました。
- 面白系をもっと増やそうと思います。
- もう少し「人間っぽい」パターンと「機械っぽい」パターンを継続し、ネガポジを見極めます。
- 毎分、1分以内の物にしか提案させないようにしました。
- これはもう、面白系の率を増やすしか無いかと思います。
- その人の過去Tweetの内容やTweet時間帯、プロフィール内容、Follower/Followの人たちを自動分析した上で出せれば究極。いつか、余力があったら。
コード
テーブル構造は最終的に下記の通り。
+------------+----------+------+-----+---------+-------+ | Field | +------------+----------+------+-----+---------+-------+ | tweet_id | TwitterのStatusID | user_id | TwitterのuserのID | user_name | Twitterのscreen_name | tweet_date | 寝坊Tweetの日時 | reply_date | 言い訳提案Replyの日時 | tweet | 寝坊Tweetの文言 | reply | 言い訳提案Replyの文言 +------------+----------+------+-----+---------+-------+
cron的に 「* 7-8 * * 1-5」(月曜~金曜 7時~8時 毎分)として動かすコードは下記の通り。
<?php
// initialize
require 'twitteroauth/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;
// configure
$consumerKey = 'consumer keyを入れて下さい';
$consumerSecret = 'consumer secretを入れて下さい';
$accessToken = 'access tokenを入れて下さい';
$accessTokenSecret = 'access token secretを入れて下さい';
$db_host = 'dbのhost';
$db_user = 'dbのuser';
$db_pass = 'dbのpass';
$db_name = 'dbのname';
//$reply_tweet = 'もしかして寝坊しましたか?相手が納得出来る遅刻の言い訳を作るAndroidアプリは http://curious4dev.mydns.jp/ewake/redirect.php?tid=';
$reply_tweet = array('寝坊を検知しました。遅刻の言い訳を提案します。','もしかして寝坊しましたか?勝手に遅刻の言い訳を考えました!');
$sql_select = 'select count(1) as count from ewakeLog where date_add(reply_date, interval 24 hour) > now() and user_id = :user_id;';
$sql_insert = 'insert into ewakeLog (tweet_id, user_id, user_name, tweet, reply, tweet_date, reply_date) values(:tweet_id, :user_id, :user_name, :tweet, :reply, :tweet_date, now());';
// load file
$ewake_text = file('ewake.txt');
// conenct to mysql
$pdo = new PDO("mysql:dbname=" . $db_name, $db_user, $db_pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"));
// create Twitter object and search from tweets
$twObj = new TwitterOAuth($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
$search_key = "寝坊した";
$options = array('q' => $search_key, 'count' => '100', 'lang' => 'ja');
$json = $twObj->get('search/tweets', $options);
// check tweets
foreach ($json->statuses as $result) {
// get parameters from tweet
$tweet_id = $result->id_str;
$user_id = $result->user->id_str;
$tweet = $result->text;
$user_name = $result->user->screen_name;
$created_at = $result->created_at;
// delete \n
$tweet = str_replace("\r\n", '', $tweet);
$tweet = str_replace("\n", '', $tweet);
// is Reply?
if (mb_substr_count($tweet, '@') > 0 ) {
$isReply = true;
} else {
$isReply = false;
}
// is RT?
if (strpos($tweet, "RT") ==false) {
$isRT = false;
} else {
$isRT = true;
}
// is寝坊した?
if (mb_strpos($tweet, $search_key) ==false) {
$isNebou = false;
} else {
$isNebou = tue;
}
// with HashTag?
if (strpos($tweet, "#") == false) {
$isHashTag = false;
} else {
$isHashTag = true;
}
// is Fresh Tweet?(less than 1 minute)
$now = strtotime("-1 min");
$check = strtotime($created_at);
if($now <= $check) {
$isFresh = true;
} else {
$isFresh = false;
}
// check already send last 24 hour
$statement = $pdo->prepare($sql_select);
$statement->bindValue(':user_id', $user_id, PDO::PARAM_INT);
$statement->execute();
$count = 0;
if ($row = $statement->fetch()) $count = $row['count'];
if ($count == 0) {
$isAlreadySend = false;
} else {
$isAlreadySend = true;
}
// send reply when not reply and not RT and not send
if ($isReply == false && $isRT == false && $isAlreadySend == false && $isHashTag == false && $isFresh == true && $isNebou == true) {
// send reply
$tmp_text = $ewake_text[mt_rand(0,count($ewake_text)-1)];
$tmp_text = str_replace("\r",'',$tmp_text);
$tmp_text = str_replace("\n",'',$tmp_text);
$tmp_text = str_replace("\r\n",'',$tmp_text);
$ewake = $reply_tweet[mt_rand(0,1)] . '「' . $tmp_text .'」';
$reply = '@' . $user_name. ' '. $ewake;
$reply_json = $twObj -> post('statuses/update', ['status'=>$reply, 'in_reply_to_status_id'=>$tweet_id]);
// insert to log when success
$created_at = date('Y-m-d H:i:s', strtotime($created_at));
$statement = $pdo->prepare($sql_insert);
$statement->bindParam(':tweet_id', $tweet_id, PDO::PARAM_STR);
$statement->bindParam(':user_id', $user_id, PDO::PARAM_STR);
$statement->bindParam(':tweet', $tweet, PDO::PARAM_STR);
$statement->bindParam(':reply', $reply, PDO::PARAM_STR);
$statement->bindParam(':tweet_date', $created_at, PDO::PARAM_STR);
$statement->bindParam(':user_name', $user_name, PDO::PARAM_STR);
$statement->execute();
}
}
?>
コードの中で、A/Bテスト用パラメータとして、人間っぽいのと機械っぽいのを設定しているのが下記の部分で、
$reply_tweet = array('寝坊を検知しました。遅刻の言い訳を提案します。','もしかして寝坊しましたか?勝手に遅刻の言い訳を考えました!');
↑の2つのどっちかをランダムに冒頭部分で使い、reply文言を生成してます。
$ewake = $reply_tweet[mt_rand(0,1)] . '「' . $tmp_text .'」';
あとは、
- 寝坊ツイートの中に @ が入っていたら提案しない
- 寝坊ツイートの中に # が入っていても提案しない
- RTされた寝坊ツイートにも提案しない
- 本当に「寝坊した」が含まれていないと提案しない
- 取得時点から1分以内のものにしか提案しない
- 24時間以内に同一寝坊者に再提案しない
という条件を定めています。
採用事例
採用してくれると、ちょっと嬉しい。
しかし、たまに「本当に人が送ってくれている」と誤認されている方がいらっしゃるようです。丁寧な御礼のリプライを頂いた事例が3例あり、いずれも年齢層若いような感じでした。
ネガにしろポジにしろ、反応がすぐに返ってくるから楽しいです。
もう、アプリじゃなくても良いんじゃないか?という考えが一瞬だけ頭をよぎりましたが、それは考えちゃダメだな、と。
明日の朝7:00~08:59がいよいよ平日の本番となります。
以上、よろしくお願い致します。
関連記事
-
-
街頭インタビュー 実装 #2
お疲れ様です。高橋です。 本日の実装状況 街頭インタビューを構成する要素を、徹底 …
-
-
遅刻の言い訳アプリをリリースしてみた。
お疲れ様です。高橋です。 2/20あたりから、「合理的な遅刻の言い訳生成アプリ。 …
-
-
広告IDが取得出来なかった理由がわかってきた。かな?
お疲れ様です。高橋です。 しばらく前からめぼしい更新を停止していた「カナかな?」 …
-
-
Google Play Developer登録
お疲れ様です。高橋です。 本日は引き続きwordpress周りの設定を行うと同時 …
-
-
Win7(64bit)+Unity4.5.5f1で作った物をAndroidエミュで動かしてみた
お疲れ様です。高橋です。 先ほどはcocosを使ったサンプルをエミュで動かす所ま …
-
-
Androidアプリで画面遷移してもBGMが鳴り続けるようにしてみた。
お疲れ様です。高橋です。 先日無事にDAWで楽曲を作成してandroidアプリか …
-
-
街頭インタビュー 背景人物切り替え機能の実装
お疲れ様です。高橋です。 本日は、背景人物を切り替える機能を実装しました。とりあ …
-
-
遅刻の言い訳提案システム 稼働二日目
お疲れ様です。高橋です。 遅刻の言い訳提案システムについて、先日課題として上げた …
-
-
アプリログをQlikViewでリアルタイムに可視化してみた。
お疲れ様です。高橋です。 タイトルは本当だと「アプリが送るログをhttpdが受け …
-
-
TwitterアナリティクスからCSVがダウンロード出来ない
お疲れ様です。高橋です。 TwitterアナリティクスのCSV 遅刻の言い訳提案 …

