Skip to content
This repository has been archived by the owner on Mar 10, 2020. It is now read-only.

Mission3_3nan3 #32

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
48 changes: 48 additions & 0 deletions 3nan3/3nan3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
### ���e���œV�C�𕷂��i�l�ȓ��e������j�Ɨ\�񂪓��e�����
(update:2015/06/24)

�C���[�W

> �����̓����̓V�C�́H

�Ɠ��e����ƁA

>> �����̓����̓V�C�͓܂�̂�����ł�

�����b�Z�[�W�Ƃ��Ďc��悤�ɂȂ��Ă��܂��B

* �ڍא���

�󗝂��郁�b�Z�[�W��`(�����E�����E������E[��]��)([�n��]��)�V�C�́H`
�n�������‚���Ȃ���΁iDB�ɓo�^����ĂȂ���΁j�\��͂ł��Ȃ��悤�ɂȂ��Ă��܂�
���t�ō����E�����E������ȊO���w�肳���Ƃ��̒n��̗\��T�v�������e����܂�
���t�ƒn���͏����t�ł��󗝂ł���悤�ɂȂ��Ă��܂��B�܂��A"��"�^"�H"�͏ȗ��‚ł�

�V�C�\��̏���Livedoor�̂��V�CAPI�������Ă��Ă܂�
http://weather.livedoor.com/forecast/webservice/json/v1?city=400040

* �R�[�h�̗v��

���b�Z�[�W���󗝂��邩�ǂ����͎��̂悤�ɒ��ׂĂ��܂�(app.php:27)
`preg_match('/^(.+��){1,2}�V�C(�́H?)?$/u', $body)`

API�ł͒n����w�肷�邽�߂�ID���K�v�ƂȂ�A���O��DB�ɒn����ID��o�^���Ă��������̂���n�����w�肵��ID���擾���Ă��܂�
�����A�O�q�̂Ƃ����ɒn�������邩���t�����邩�킩��Ȃ��̂ŁA�n�����}�b�`���邩���m���߂Ă��猈�肵�Ă��܂��B(Application.php:176-189)
`
$split = preg_split("/��/u", $message, -1, PREG_SPLIT_NO_EMPTY);
$cityObj = $this['repository.weather']->getCity($split[0]);
if($cityObj != null) {
$dateLabel = $split[1];
}
else {
$cityObj = $this['repository.weather']->getCity($split[1]);
$dateLabel = $split[0];
if($cityObj == null) {
return '������Ƃ킩��Ȃ������ˁ[';
}
}`

�n����ID�̌��ѕt���͈ȉ��Q�ƂƂ̎��ł����B
http://weather.livedoor.com/forecast/rss/primary_area.xml


4 changes: 4 additions & 0 deletions 3nan3/saxsir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
saxsir
===

hoooooooooo!!
27 changes: 13 additions & 14 deletions 3nan3/web-server/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,24 @@
$username = isset($data['username']) ? $data['username'] : '';
$body = isset($data['body']) ? $data['body'] : '';

if($body == "uranai") {
switch (rand(0, 2)) {
case 0:
$body = "大吉";
break;
case 1:
$body = "吉";
break;
case 2:
$body = "凶";
break;
}
if(1 == preg_match('/^(.+の){1,2}天気(は??)?$/u', $body)) {
$body = $app->getWeatherMessage($body);
}

$createdMessage = $app->createMessage($username, $body, base64_encode(file_get_contents($app['icon_image_path'])));

return $app->json($createdMessage);
});

$app->get('/weather/{dateLabel}/{city}', function ($dateLabel, $city) use ($app) {
return $app->getWeatherMessage($dateLabel.'の'.$city.'の天気は');
});

// FIXME 地域名→id変換用のDBを初期化&データ挿入するんだけど、こんなところじゃなくてもっといいところ(?)で
/*$app->get('/init_weather', function () use ($app) {
return $app->initWeatherCity();
});*/

$app->delete('/messages/{id}', function ($id) use ($app) {
$app->deleteMessage($id);

Expand Down
4 changes: 4 additions & 0 deletions 3nan3/web-server/db/001_setup.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS vg_weather_city (
id INTEGER,
title TEXT
);
32 changes: 32 additions & 0 deletions 3nan3/web-server/src/My1DayServer/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function __construct(array $values = array())
$this->configureDefaultIconImagePath();

$this->configureRepository();
$this->configureWeather();
}

public function configureLogger()
Expand Down Expand Up @@ -90,8 +91,14 @@ public function configureError()
public function configureRepository()
{
$this['repository.message'] = function($app) { return new Repository\MessageRepository($app['db']); };
$this['repository.weather'] = function($app) { return new Repository\WeatherCityRepository($app['db']); };
}

public function configureWeather()
{
$this['weather'] = function($app) { return new Weather(); };
}

public function configureApiSchemaValidator()
{
$this['schema_validator'] = new ApiSchemaValidator();
Expand Down Expand Up @@ -164,6 +171,31 @@ public function createMessage($username, $body, $icon)
return $this->getMessage($id);
}

public function getWeatherMessage($message)
{
$split = preg_split("/の/u", $message, -1, PREG_SPLIT_NO_EMPTY);
$cityObj = $this['repository.weather']->getCity($split[0]);
if($cityObj != null) {
$dateLabel = $split[1];
}
else {
$cityObj = $this['repository.weather']->getCity($split[1]);
$dateLabel = $split[0];
if($cityObj == null) {
// TODO IPから現在位置取得したい
//$cityObj = $this['repository.weather']->getCity("東京");
return 'ちょっとわかんないっすねー';
}
}

return $this['weather']->forecast($dateLabel, $cityObj);
}

public function initWeatherCity()
{
$this['repository.weather']->registCityFromXml();
}

protected function getBaseTimezone()
{
if ($this->tz !== null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace My1DayServer\Repository;

class WeatherCityRepository
{
protected $conn;
private $tableName = 'vg_weather_city';

public function __construct($conn)
{
$this->conn = $conn;
}

/*
* vg_weather_cityの初期化&データ挿入だからむやみに実行しない
*/
public function registCityFromXml() {

$obj = $this->getPrimaryAreaXml();

$this->deleteAllCity();
foreach($obj['channel']['ldWeather_source']['pref'] as $pref) {
if(array_values($pref['city']) === $pref['city']) { // 要素が一つだと(数値の)配列にならないので連想配列かどうかで判断
foreach($pref['city'] as $city) {
$this->createCity($city['@attributes']['id'], $city['@attributes']['title']);
}
}
else {
$city = $pref['city'];
$this->createCity($city['@attributes']['id'], $city['@attributes']['title']);
}
}
}

private function getPrimaryAreaXml() {
$xml = file_get_contents('http://weather.livedoor.com/forecast/rss/primary_area.xml');
// xmlタグの名前空間(:で区切られるやつ)がうまくパース出来ないので_に置き換える
$xml = preg_replace("/<([^>]+?):(.+?)>/", "<$1_$2>", $xml);
$xmlObject = simplexml_load_string($xml);
return json_decode( json_encode($xmlObject), true);
}

public function getCity($title)
{
$sql = 'SELECT * FROM '.$this->tableName.' WHERE title = ?';
$params = [$title];

return $this->conn->fetchAssoc($sql, $params);
}

private function deleteAllCity()
{
$sql = 'DELETE FROM '.$this->tableName;
$params = [];

$this->conn->executeUpdate($sql, $params);
}

private function createCity($cityId, $cityTitle)
{
$data = array(
'id' => $cityId,
'title' => $cityTitle,
);

$queryResult = $this->conn->insert($this->tableName, $data);
if (!$queryResult) {
return false;
}
return true;
}
}
42 changes: 42 additions & 0 deletions 3nan3/web-server/src/My1DayServer/Weather.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace My1DayServer;

class Weather
{
public function forecast($dateLabel, $city) {
$obj = $this->getWeatherForecast($city['id']);
if($obj == null) { return 'ちょっとわかんないですねー'; }

$message = null;
foreach($obj['forecasts'] as $forecast) {
if($forecast['dateLabel'] == $dateLabel) {
$message = $dateLabel."の".$city['title']."の天気は".$forecast['telop']."でしょう";
}
}
if($message == null) {
$message = $obj['description']['text'];
}

return $message;
}

/*
* Livedoor Weather Web ServiceのREST APIから天気予報取得
*/
private function getWeatherForecast($city_id) {
$ch = curl_init();
$url = "http://weather.livedoor.com/forecast/webservice/json/v1";
$options = array(
CURLOPT_URL => $url.'?city='.$city_id,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60, // TODO 失敗した場合どうなるのか
CURLOPT_CUSTOMREQUEST => "GET",
);
curl_setopt_array($ch, $options);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response;
}
}