Archive | アプリ RSS feed for this section

ペルソナQ攻略情報 このエントリーをはてなブックマークに追加

1 5月

どんなアプリ?

3DSのゲーム「ペルソナQ」を進めていくうちに、あのスキルはどのサブペルソナで取得するんだっけ?このキャラ耐性なんだっけ?でもwiki見るのめんどい!ということが増えてきたので、とりあえずスキルの逆引きとキャラクターの基本情報を確認できるようにしました。

使った技術

このアプリでは、スキル逆引き画面(以下の画像)にカスタムリストビューを使っています。ひとつひとつのスキルの角丸ボックスはXMLで表現。

ハマったところ

スキルによって、表示したい項目が違うのですが(例えば、魔法には消費SP、対象、回数など項目が多いが、パッシブスキルには回復量など、項目が少ない)、データソースは同じ。

データベースでいうと、テーブルひとつに全データ突っ込んでる状態なので。この種類のデータのときはこう表示したい、という要望がありました。

しかし、リストビューのひとつひとつのアイテム内でビューをごちゃごちゃするとエラーでまくり。結局、リストビューのときはビューをごちゃごちゃしないほうがいいということがわかり、種類によってビュー自体を切り替えることにしました。

ダウンロード

ストアでダウンロードする

ユニゾン時間割 このエントリーをはてなブックマークに追加

1 5月

どんなアプリ?

大人気スマホアプリ、「ユニゾンリーグ」では、装備の強化・進化に必要な素材をクエストで集める必要があります。

自分の狙った素材を効率よく集めるには、それぞれに応じたクエストをこなす必要があるのですが、そのクエストというのが曜日によって出現時刻がバラバラ!

攻略wikiや2ch、まとめサイトを見ればわかるのですが、いちいち調べたり今日は…えーっと…とやるのが面倒なので、こんなアプリを作りました。

  • 今やっているクエストを表示
  • 自分の狙ったクエストの開始時刻が近づくとプッシュ通知がくる
  • 明日のクエストを表示

使った技術

このアプリでは、時間割情報と端末の登録IDをサーバに保存し、サーバ内でcrontabを実行して時間が近づくと登録IDに向けてPUSH通知を送信。受信側では、自分の指定したクエストの通知であれば通知エリアに表示を出す、ということをやっています。

ハマったところ

はじめてグラフィカルな画面のアプリを作ったので、画面デザインの基礎知識がなく、低解像度の画像で画面設計してしまい、なんだかディザが目立ってしまいました…。画面サイズを720×1280として設計したら、キレイに表示されるようになりました。

ダウンロード

ストアでダウンロードする

Calendarクラス このエントリーをはてなブックマークに追加

11 3月

Pearのカレンダークラスはちょっと古いとか、別にビューは自分で書くから日付計算だけしてくれればいいなとか、そもそもpear install calendar-betaって、ベータかよ!とか、そういうことを思ったので、Pearのカレンダークラスを参考に作りました。
カレンダークラス

<?php
class Calendar
{
  private $year, $month, $day;
  private $prevYear, $prevMonth;
  private $nextYear, $nextMonth;
  public $week = array();
  private $timestamp;

  public function __construct($y = null, $m = null, $d = null, $firstDay = null, $is_padding = false)
  {
    $this->year = is_null($y) ? intval(date('Y')) : (int)$y;
    $this->month = is_null($m) ? intval(date('m')) : (int)$m;
    $this->day = is_null($d) ? intval(date('d')) : (int)$d;
    $this->is_padding = (bool)$is_padding;
    if (is_null($firstDay) || $firstDay < 0 || $firstDay > 6){
      $firstDay = 0;
    }
    $this->firstDay = $firstDay;

    $this->nextYear  = mktime(0, 0, 0, $this->month, 1, $this->year+1);
    $this->nextMonth = mktime(0, 0, 0, $this->month+1, 1, $this->year);
    $this->nextDay = mktime(0, 0, 0, $this->month, $this->day+1, $this->year);
    $this->prevYear  = mktime(0, 0, 0, $this->month, 1, $this->year-1);
    $this->prevMonth = mktime(0, 0, 0, $this->month-1, 1, $this->year);
    $this->prevDay = mktime(0, 0, 0, $this->month, $this->day-1, $this->year);

    $this->init();
  }

  /**
   * generate Calendar
   */
  private function init()
  {
    $this->timestamp = mktime(0, 0, 0, $this->month, $this->day, $this->year);

    // パディング
    if (date('w', $this->timestamp) != $this->firstDay){
      $prevMonth = date('t', mktime(0, 0, 0, $this->month-1, 1, $this->year)); // 先月の最終日
      if ($this->firstDay == 0){
        $paddings = date('w', $this->timestamp); // 始まりが月曜日
      } else {
        $paddings = 7-$this->firstDay+date('w', $this->timestamp);
        if ($paddings > 7){
          $paddings = $paddings % 7;
        }
      }
      // 先月のパディングすべき日から、先月末までパディングする
      for($i = $prevMonth-$paddings+1; $i <= $prevMonth; $i++){
        $thisTime = mktime(0, 0, 0, $this->month-1, $i, $this->year);
        $firstDay = false;
        if ($i == $prevMonth-$paddings){
          $firstDay = true;
        }
        $this->week[] = new Day($thisTime, $firstDay, false, $this->is_padding, false);
      }
    }

    // 今月の日付
    $counter = 1;
    for ($i = 1; $i <= date('t', $this->timestamp); $i++){
      $thisTime = mktime(0, 0, 0, $this->month, $i, $this->year);
      $firstDay = false;
      $lastDay = false;
      if (date('w', $thisTime) == $this->firstDay){
        $firstDay = true;
        $counter = 1;
      } else {
        if (($this->firstDay == 0 && date('w', $thisTime) == 6) || $this->firstDay-1 == date('w', $thisTime)){
          $lastDay = true;
        }
        $counter++;
      }
      $this->week[] = new Day($thisTime, $firstDay, $lastDay, true, true);
    }

    // パディング
    if ($lastDay == false){
      $lastW = date('w', $thisTime);
      echo $counter;
      for ($i = 1; $i <= 7-$counter; $i++){
        $time = mktime(0, 0, 0, $this->month+1, $i, $this->year);
        $lastDay = ($i == 7-$counter) ? true : false;
        $this->week[] = new Day($time, false, $lastDay, $this->is_padding, false);
      }
    }
  }

  /**
   * getter methods
   */
  public function getYear()
  {
    return $this->year;
  }

  public function getMonth()
  {
    return $this->month;
  }

  public function getDay()
  {
    return $this->day;
  }

  public function getPrevYear()
  {
    return $this->prevYear;
  }

  public function getPrevMonth()
  {
    return $this->prevMonth;
  }

  public function getNextYear()
  {
    return $this->nextYear;
  }

  public function getNextMonth()
  {
    return $this->nextMonth;
  }
}

class Day
{
  private $timestamp = null;
  private $firstDay = false;
  private $lastDay = false;
  private $is_display = true;
  private $is_thisMonth = true;
  private $y, $m, $d, $week;

  public function __construct($timestamp = 0, $firstDay = false, $lastDay = false, $is_display = true, $is_thisMonth = true)
  {
    $this->timestamp = $timestamp;
    $this->firstDay = $firstDay;
    $this->lastDay = $lastDay;
    $this->is_display = $is_display;
    $this->is_thisMonth = $is_thisMonth;

    $this->y = date('Y', $timestamp);
    $this->m = date('n', $timestamp);
    $this->d = date('j', $timestamp);
    $this->week = date('w', $timestamp);
  }

  /**
   * return Timestamp
   */
  public function getTimestamp()
  {
    return $this->timestamp;
  }

  /**
   * 今日?
   */
  public function isToday()
  {
    if (date('Ymd', $this->timestamp) == date('Ymd')){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 日曜日?
   */
  public function isSunday()
  {
    if ($this->thisWeek() == 0){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 土曜日?
   */
  public function isSaturday()
  {
    if ($this->thisWeek() == 6){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 日オブジェクトの年を返す
   */
  public function thisYear()
  {
    return $this->y;
  }

  /**
   * 日オブジェクトの月を返す
   */
  public function thisMonth()
  {
    return $this->m;
  }

  /**
   * 日オブジェクトの日を返す
   */
  public function thisDay()
  {
    if ($this->is_display){
      return $this->d;
    } else {
      return null;
    }
  }

  /**
   * 日オブジェクトの曜日を返す
   */
   public function thisWeek()
   {
      return $this->week;
   }

  /**
   * この日オブジェクトが今月のものか調べる
   * 先月・来月をパディングしている日オブジェクトならfalseになる
   */
  public function isThisMonth()
  {
    return $this->is_thisMonth;
  }

  /**
   * この日オブジェクトが週のはじまりか調べる
   */
  public function isFirst()
  {
    return $this->firstDay;
  }

  /**
   * この日オブジェクトが週の終わりか調べる
   */
  public function isLast()
  {
    return $this->lastDay;
  }
}

使うとき

<php?
$cal = new Calendar(date('Y'), date('m'), 0, true);
php>

  <ul>
    <li><?php echo $cal->getPrevYear() ?>年 <?php echo $cal->getPrevMonth() ?> 月</li>
    <li><?php echo $cal->getYear() ?>年 <?php echo $cal->getMonth() ?>月</li>
    <li><?php echo $cal->getNextYear() ?>年 <?php echo $cal->getNextYear() ?>月</li>
  </ul>

  <table class="table table-bordered nopadding">
    <tr>
      <th class="sun">日</th>
      <th>月</th>
      <th>火</th>
      <th>水</th>
      <th>木</th>
      <th>金</th>
      <th class="sat">土</th>
    </tr>
<?php foreach ($cal->week as $week): ?>
  <?php if($week->isFirst()): ?>
    <tr>
  <?php endif ?>

  <?php if ($week->isThisMonth()): ?>
      <td class="
        <?php echo $week->isSunday()? 'sun' : ''; ?>
        <?php echo $week->isSaturday()? 'sat' : ''; ?>
        <?php echo $week->isToday()? ' today' : ''; ?>">
        <ul class="nav nav-list">
          <li class="active"><a href="#"><?php echo $week->thisDay(); ?></a></li>
        </ul>
      </td>
  <?php else: ?>
      <td class="empty
        <?php echo $week->isSunday()? 'sun' : ''; ?>
        <?php echo $week->isSaturday()? 'sat': ''; ?>">
        <ul class="nav nav-list">
          <li class="active"><a href="#"><?php echo $week->thisDay(); ?></a></li>
        </ul>
      </td>
  <?php endif ?>

  <?php if($week->isLast()): ?>
    </tr>
  <?php endif ?>

<?php endforeach ?>
  </table>

コンストラクタ引数

第1引数:カレンダーの年。デフォルト今年。
第2引数:カレンダーの月。デフォルト今月。
第3引数:初まり曜日の指定(0=月曜、6=土曜)。デフォルト日曜日。
第4引数:初週、終週に先月・来月の数字があったとき、表示するかどうか。デフォルト非表示

カレンダークラスのメソッド

int getYear(), getMonth(), getDay():コンストラクタに渡した値から生成した、年・月・日を数字で返す。
int getPrevYear(), getPrevMonth():先月の年・月を数字で返す。
int getNextYear(), getNextMonth():来月の年・月を数字で返す。

カレンダークラスを生成すると、指定したパラメタで、カレンダーの中身であるDayクラスのインスタンスを配列にしたものを作ります。(init()で作成)
これを、foreach等でループさせることで、カレンダーを表示していきます。
foreachでループさせる、Dayクラスのメソッド

timestamp getTimestamp():その日のタイムスタンプを返す。
bool isToday():今日かどうか(今、動かしているその日か)をboolで返す。
bool isSunday(), isSaturday():それぞれ日曜日か、土曜日かをboolで返す。
int thisYear(), thisMonth(), thisDay():それぞれ年月日を返す。日については、コンストラクタの第4引数でfalse指定の場合、nullが返る(今月のカレンダーから見える先月の終わりのほうや来月のはじめのほうの日付を非表示とする、という設定だから。)
int thisWeek():その日の曜日を返す。0=日曜、6=土曜
book isThisMonth():コンストラクタで指定した月かどうか調べる。trueなら今月、falseなら来月か先月。
bool isFirst():コンストラクタで指定した始まりの曜日からして、初めの曜日であるかどうか。例えば、0(日曜)を指定していたとき、日曜ならtrue
bool isLast():コンストラクタで指定した始まりの曜日からして、最後の曜日であるかどうか。例えば、0(日曜)を指定していたとき、土曜ならtrue

ひとまず、自分が使うのはこんなところなので、こんなクラスを作ってみました。

これをsymfonyのlib/uril/Calendar.phpとかに置いといたら、きっとPEARのCalendarクラスより簡単にカレンダーを使える気がする!

スタイル等適用したら、こんなかんじになります