Пример #1
0
 /**
  * Study Page Search
  * 
  * Convert the search term to a framenum parameter and forward to index.
  * 
  * @url  /study/search/:search
  *
  */
 public function executeEdit($request)
 {
     $search = trim($request->getParameter('id', ''));
     if (!empty($search)) {
         $search = CJK::normalizeFullWidthRomanCharacters($search);
         // update search box with cleaned up search term
         $request->setParameter('search', str_replace('_', '/', $search));
         $framenum = KanjisPeer::getFramenumForSearch($search);
     }
     if ($request->getMethod() === coreRequest::POST) {
         // Handle POST request from EditStory component.
         $this->forward404Unless(BaseValidators::validateInteger($framenum) && intval($framenum));
         // Learned kanji (doLearned.x, from input type="image")
         if ($request->hasParameter('doLearned_x')) {
             LearnedKanjiPeer::addKanji($this->getUser()->getUserId(), $framenum);
             // redirect to next restudy kanji
             $next = ReviewsPeer::getNextUnlearnedKanji($this->getUser()->getUserId());
             if ($next !== false) {
                 $this->redirect('study/edit?id=' . $next);
             }
         }
     }
     $request->setParameter('framenum', $framenum);
     if ($framenum) {
         $this->framenum = $framenum;
         $this->kanjiData = (object) KanjisPeer::getKanjiById($this->framenum);
         $this->getResponse()->setTitle('Study: ' . $this->kanjiData->kanji . ' "' . $this->kanjiData->keyword . '"');
     } else {
         $this->framenum = false;
     }
 }
Пример #2
0
 public function execute($request)
 {
     $user_id = coreContext::getInstance()->getUser()->getUserId();
     $this->filter = $this->getUser()->getLocalPrefs()->get('review.graph.filter', '');
     $carddata = ReviewsPeer::getLeitnerBoxCounts($this->filter);
     $this->restudy_cards = $carddata[0]['expired_cards'];
     // count untested cards and add to graph
     $this->untested_cards = ReviewsPeer::getCountUntested($user_id, $this->filter);
     $carddata[0]['fresh_cards'] = $this->untested_cards;
     $carddata[0]['total_cards'] += $this->untested_cards;
     // count totals (save a database query)
     //$this->total_cards = 0;
     $this->expired_total = 0;
     for ($i = 0; $i < count($carddata); $i++) {
         $box =& $carddata[$i];
         //$this->total_cards += $box['total_cards'];
         // count expired cards, EXCEPT the red stack
         if ($i > 0) {
             $this->expired_total += $box['expired_cards'];
         }
     }
     $this->chart_data = $this->makeChartData($carddata);
     //DBG::printr($this->chart_data);exit;
     $this->me = $this;
     return coreView::SUCCESS;
 }
Пример #3
0
 public function executeProgress()
 {
     // determine active lesson if the user has added cards in order,
     //  otherwise set to FALSE
     $cur_frame = ReviewsPeer::getHeisigProgressCount($this->getUser()->getUserId());
     $this->currentLesson = $cur_frame ? rtkBook::getLessonForFramenum($cur_frame + 1) : false;
     // find the success/fail flashcard count per lesson
     $progress = ReviewsPeer::getProgressStatus($this->getUser()->getUserId());
     // rtk lesson data
     $rtkLessons = rtkBook::getLessons();
     // how many lessons have been started
     $this->activeLessons = 0;
     $lessons = array();
     for ($i = 1; $i <= 56; $i++) {
         $lessons[$i] = array('label' => 'Lesson ' . $i, 'passValue' => 0, 'failValue' => 0, 'testedCards' => 0, 'totalCards' => 0, 'maxValue' => $rtkLessons[$i]);
     }
     foreach ($progress as $p) {
         if ($p->lessonId <= 0) {
             throw new coreException('Bad lesson id');
         }
         // fixme: only RtK1 for now
         if ($p->lessonId > 56) {
             break;
         }
         $lessons[$p->lessonId] = array('label' => 'Lesson ' . $p->lessonId, 'passValue' => $p->pass, 'failValue' => $p->fail, 'testedCards' => $p->pass + $p->fail, 'totalCards' => $p->total, 'maxValue' => $rtkLessons[$p->lessonId]);
         $this->activeLessons++;
     }
     $this->lessons = $lessons;
 }
Пример #4
0
 /**
  * Return EditStory component based on GET or POST request.
  * 
  * PARAMS
  *   framenum       Valid kanji id (frame number)
  *   kanjiData      Kanji data for kanji id
  *   reviewMode     True if called from the Review page
  *   
  * POST  requests to update the story for current user.
  * 
  *   character      Current kanji (utf8)
  *   chkPublic      Public story
  *   txtStory       Story
  * 
  * 
  * @return 
  * @param object $request
  */
 public function execute($request)
 {
     if ($request->getMethod() !== coreRequest::POST) {
         // get user's story
         $story = StoriesPeer::getStory($this->getUser()->getUserId(), $this->framenum);
         if ($story) {
             $request->getParameterHolder()->add(array('txtStory' => $story->text, 'chkPublic' => $story->public));
         }
     } else {
         $validator = new coreValidator($this->getActionName());
         if ($validator->validate($request->getParameterHolder()->getAll())) {
             if ($request->hasParameter('doUpdate')) {
                 $txtStory = trim($request->getParameter('txtStory', ''));
                 $txtStory = strip_tags($txtStory);
                 // delete empty story
                 if (empty($txtStory)) {
                     StoriesPeer::deleteStory($this->getUser()->getUserId(), $this->framenum);
                 } else {
                     StoriesPeer::updateStory($this->getUser()->getUserId(), $this->framenum, array('text' => $txtStory, 'public' => $request->hasParameter('chkPublic') ? 1 : 0));
                 }
                 $request->setParameter('txtStory', $txtStory);
             }
         }
     }
     // set state
     $request->setParameter('framenum', $this->framenum);
     if (!$request->hasParameter('reviewMode')) {
         $this->isRestudyKanji = ReviewsPeer::isRestudyKanji($this->getUser()->getUserId(), $this->framenum);
         $this->isRelearnedKanji = LearnedKanjiPeer::hasKanji($this->getUser()->getUserId(), $this->framenum);
     }
     $this->formatted_story = StoriesPeer::getFormattedStory($request->getParameter('txtStory', ''), $this->kanjiData->keyword, true);
     return coreView::SUCCESS;
 }
Пример #5
0
 /**
  * Delete all given flashards, returns an array of ids of flashcards
  * that were succesfully deleted.
  * 
  * @param object $userId
  * @param object $selection
  * 
  * @return array  Array of successfully deleted flashcards (ids) or false
  */
 public static function deleteSelection($userId, array $cardSelection)
 {
     $cards = ReviewsPeer::deleteFlashcards($userId, $cardSelection);
     if (is_array($cards) && count($cards)) {
         ActiveMembersPeer::updateFlashcardCount($userId);
     }
     return $cards;
 }
Пример #6
0
 public function execute($request)
 {
     $queryParams = $this->getUser()->getLocalPrefs()->syncRequestParams('detailedflashcardlist', array(uiSelectPager::QUERY_ROWSPERPAGE => 20, uiSelectTable::QUERY_SORTCOLUMN => 'framenum', uiSelectTable::QUERY_SORTORDER => 0));
     $this->pager = new uiSelectPager(array('select' => ReviewsPeer::getDetailedFlashcardList($this->getUser()->getUserId()), 'internal_uri' => 'review/flashcardlist', 'query_params' => $queryParams, 'max_per_page' => $queryParams[uiSelectPager::QUERY_ROWSPERPAGE], 'page' => $request->getParameter(uiSelectPager::QUERY_PAGENUM, 1)));
     $this->pager->init();
     $this->table = new uiSelectTable(new FlashcardListBinding(), $this->pager->getSelect(), $request->getParameterHolder());
     $this->table->configure(array('sortColumn' => $queryParams[uiSelectTable::QUERY_SORTCOLUMN], 'sortOrder' => $queryParams[uiSelectTable::QUERY_SORTORDER]));
 }
Пример #7
0
 /**
  * Component variables:
  * 
  *   ts_start   Timestamp from the review session start time
  * 
  * @param object $request
  */
 public function execute($request)
 {
     $queryParams = $this->getUser()->getLocalPrefs()->syncRequestParams('reviewsummary', array(uiSelectPager::QUERY_ROWSPERPAGE => 20, uiSelectTable::QUERY_SORTCOLUMN => 'framenum', uiSelectTable::QUERY_SORTORDER => 0));
     // pager
     $this->pager = new uiSelectPager(array('select' => ReviewsPeer::getReviewSessionFlashcards($this->getUser()->getUserId(), $this->ts_start), 'internal_uri' => '@review_summary', 'query_params' => $queryParams, 'max_per_page' => $queryParams[uiSelectPager::QUERY_ROWSPERPAGE], 'page' => $request->getParameter(uiSelectPager::QUERY_PAGENUM, 1)));
     $this->pager->init();
     // data table
     $this->table = new uiSelectTable(new FlashcardListBinding(), $this->pager->getSelect(), $request->getParameterHolder());
     return coreView::SUCCESS;
 }
Пример #8
0
 /**
  * Home page.
  * 
  * @return 
  */
 public function executeIndex()
 {
     if ($this->getUser()->isAuthenticated()) {
         //echo $this->getUser()->sqlLocalTime(); exit;
         // get member stats for quick summary
         $this->curFrameNum = ReviewsPeer::getHeisigProgressCount($this->getUser()->getUserId());
         $this->progress = rtkBook::getProgressSummary($this->curFrameNum);
         $this->countExpired = ReviewsPeer::getCountExpired($this->getUser()->getUserId());
         $this->countFailed = ReviewsPeer::getCountFailed($this->getUser()->getUserId());
         return 'Member';
     }
     // prepare unique homepage design
     return 'Guest';
 }
Пример #9
0
 /**
  * Transform kanji in the input Japanese text into links to the Study area,
  * and add class for Javascript popup with the Heisig keywords.
  * 
  * @param  string  $j_text  Japanese text in utf-8 from validated post data.
  * @return string  Japanese text as HTML code.
  */
 protected function transformJapaneseText($j_text)
 {
     coreToolkit::loadHelpers('Tag');
     $j_text = escape_once(trim($j_text));
     // collect associative array of known kanji => kanji, framenum, keyword
     $kanjis = ReviewsPeer::getKnownKanji($this->getUser()->getUserId(), array('kanji', 'keyword'));
     $known = array();
     foreach ($kanjis as $i => $kanjiData) {
         $known[$kanjiData['kanji']] = $kanjiData;
     }
     // wrap known kanji in text with links to Study area and hooks for javascript tooltip
     foreach ($known as $kanji => $info) {
         $url = '/study/?search=' . $info['framenum'];
         $rep = '<a href="' . $url . '" class="j" title="' . $info['keyword'] . '">' . $kanji . '</a>';
         $j_text = str_replace($kanji, $rep, $j_text);
     }
     // assumes lines end with \r\n
     $j_text = preg_replace('/[\\r\\n]+/', '<br/>', $j_text);
     return $j_text;
 }
Пример #10
0
 public function executeIndex($request)
 {
     $username = $request->getParameter('username');
     if (!$username) {
         if ($this->getUser()->isAuthenticated()) {
             $username = $this->getUser()->getUserName();
         } else {
             // if unauthenticated user checks his (bookmarked?) profile, go to login and back
             $url = $this->getController()->genUrl('profile/index', true);
             $this->getUser()->redirectToLogin(array('referer' => $url));
         }
     }
     if ($user = UsersPeer::getUser($username)) {
         $this->user = $user;
         $this->self_account = $user['username'] == $this->getUser()->getUserName();
         $this->kanji_count = ReviewsPeer::getReviewedFlashcardCount($user['userid']);
         $this->total_reviews = ReviewsPeer::getTotalReviews($user['userid']);
         $this->forum_uid = coreConfig::get('app_path_to_punbb') !== null ? PunBBUsersPeer::getInstance()->getForumUID($username) : false;
         return coreView::SUCCESS;
     }
     return coreView::ERROR;
 }
Пример #11
0
 /**
  * Study Page Search
  * 
  * Convert the search term to a framenum parameter and forward to index.
  * 
  * @url  /study/search/:search
  *
  */
 public function executeEdit($request)
 {
     // searching or browsing (previous, next buttons)
     if ($request->getMethod() === coreRequest::GET) {
         // get search term from url
         $search = trim($request->getParameter('id', ''));
         if (!empty($search)) {
             $search = CJK::normalizeFullWidthRomanCharacters($search);
             // replace characters that caused problems (dashes) with wildcard for SQL
             $search = str_replace('-', '%', $search);
             $framenum = KanjisPeer::getFramenumForSearch($search);
         }
     } else {
         // POST handled by EditStoryComponent, LearnedKanji handled here
         $framenum = $request->getParameter('framenum', false);
         // Handle POST request from EditStory component.
         $this->forward404Unless(BaseValidators::validateInteger($framenum) && intval($framenum));
         // Learned kanji (doLearned.x, from input type="image")
         if ($request->hasParameter('doLearned_x')) {
             LearnedKanjiPeer::addKanji($this->getUser()->getUserId(), $framenum);
             // redirect to next restudy kanji
             $next = ReviewsPeer::getNextUnlearnedKanji($this->getUser()->getUserId());
             if ($next !== false) {
                 $this->redirect('study/edit?id=' . $next);
             }
         }
     }
     if ($framenum) {
         $this->kanjiData = (object) KanjisPeer::getKanjiById($framenum);
         $this->getResponse()->setTitle('Study: ' . $this->kanjiData->kanji . ' "' . $this->kanjiData->keyword . '"');
         // replace search term with frame number in search box
         $request->setParameter('search', $this->kanjiData->framenum);
     } else {
         // search gave no results
         $this->kanjiData = false;
     }
 }
Пример #12
0
    <div class="clearboth"></div>
  </div>
  
  <div class="intro">
    <p>
      This list shows all your flashcards. Click a column heading to sort
      the table on that column, click more than once to revert the sort order.
      Note that in addition to the column you selected, there is always a secondary
      sorting on the frame number. Click in any row to go to the study area.
    </p>
  </div>
  <div class="stats">
    <div class="box">

      <strong>Statistics</strong><br />
      <?php 
echo ReviewsPeer::getFlashcardCount($_user->getUserId());
?>
 flashcards.<br />
    </div>
  </div>
  <div class="clear"></div>
<?php 
#DBG::user()
echo ui_select_table($table, $pager);
?>

  </div>
  </div>
</div>
Пример #13
0
 /**
  * Returns the number of related Reviews objects.
  *
  * @param      Criteria $criteria
  * @param      boolean $distinct
  * @param      PropelPDO $con
  * @return     int Count of related Reviews objects.
  * @throws     PropelException
  */
 public function countReviewss(Criteria $criteria = null, $distinct = false, PropelPDO $con = null)
 {
     if ($criteria === null) {
         $criteria = new Criteria(ImagesPeer::DATABASE_NAME);
     } else {
         $criteria = clone $criteria;
     }
     if ($distinct) {
         $criteria->setDistinct();
     }
     $count = null;
     if ($this->collReviewss === null) {
         if ($this->isNew()) {
             $count = 0;
         } else {
             $criteria->add(ReviewsPeer::IMAGES_ID, $this->id);
             $count = ReviewsPeer::doCount($criteria, false, $con);
         }
     } else {
         // criteria has no effect for a new object
         if (!$this->isNew()) {
             // the following code is to determine if a new query is
             // called for.  If the criteria is the same as the last
             // one, just return count of the collection.
             $criteria->add(ReviewsPeer::IMAGES_ID, $this->id);
             if (!isset($this->lastReviewsCriteria) || !$this->lastReviewsCriteria->equals($criteria)) {
                 $count = ReviewsPeer::doCount($criteria, false, $con);
             } else {
                 $count = count($this->collReviewss);
             }
         } else {
             $count = count($this->collReviewss);
         }
     }
     return $count;
 }
Пример #14
0
 /**
  * Kanji Flashcard review page with uiFlashcardReview
  * 
  * GET request = review page
  * 
  * 	 type = 'expired'|'untested'|'relearned'|'fresh'
  *   box  = 'all'|[1-5]
  *   filt = ''|'rtk1'|'rtk3'
  *   
  * POST request = ajax request during review
  * 
  * @param object $request
  */
 protected function reviewAction($request)
 {
     $reviewBox = $request->getParameter('box', 'all');
     $reviewType = $request->getParameter('type', 'expired');
     $reviewFilt = $request->getParameter('filt', '');
     $reviewMerge = $request->getParameter('merge') ? true : false;
     // validate
     $this->forward404Unless(preg_match('/^(all|[1-9]+)$/', $reviewBox));
     $this->forward404Unless(preg_match('/^(expired|untested|relearned|fresh)$/', $reviewType));
     $this->forward404Unless($reviewFilt == '' || preg_match('/(rtk1|rtk3)/', $reviewFilt));
     // pick title
     $this->setReviewTitle($reviewType, $reviewFilt);
     //
     $sAjaxUrl = $this->getController()->genUrl('@review');
     $options = array('partial_name' => 'review/ReviewKanji', 'ajax_url' => $sAjaxUrl, 'ts_start' => ReviewsPeer::getLocalizedTimestamp(), 'fn_get_flashcard' => array('KanjisPeer', 'getFlashcardData'), 'fn_put_flashcard' => array('ReviewsPeer', 'putFlashcardData'));
     if ($request->getMethod() !== coreRequest::POST) {
         $options['items'] = ReviewsPeer::getFlashcards($reviewBox, $reviewType, $reviewFilt, $reviewMerge);
         $this->uiFR = new uiFlashcardReview($options);
     } else {
         /*
         			if (rand(1,10) < 3)
         			{
         				sleep(6);
         			}*/
         // handle Ajax request (or throws exception)
         $oJson = coreJson::decode($request->getParameter('json', '{}'));
         if (!empty($oJson)) {
             $flashcardReview = new uiFlashcardReview($options);
             return $this->renderText($flashcardReview->handleJsonRequest($oJson));
         }
         throw new rtkAjaxException('Empty JSON Request.');
     }
     return coreView::SUCCESS;
 }
Пример #15
0
  <div class="frame">
    <ul>
<?php 
foreach (ReviewsPeer::getRestudyKanjiList($_user->getUserId()) as $R) {
    ?>
      <li<?php 
    echo $R['framenum'] == $framenum ? ' class="selected"' : '';
    ?>
>
        <span><?php 
    echo $R['framenum'];
    ?>
</span>
        <?php 
    $kw = preg_replace('/\\//', '<br/>', $R['keyword']);
    echo link_to($kw, 'study/edit?id=' . $R['framenum']);
    ?>
      </li>
<?php 
}
?>
    </ul>
    <div class="clear"></div>
  </div>
Пример #16
0
 public function executeExportflashcards()
 {
     $throttler = new RequestThrottler($this->getUser(), 'export');
     if (!$throttler->isValid()) {
         return $this->renderPartial('misc/requestThrottleError');
     }
     $csv = new ExportCSV($this->getContext()->getDatabase());
     $select = ReviewsPeer::getSelectForExport($this->getUser()->getUserId());
     $csvText = $csv->export($select, array('FrameNumber', 'Kanji', 'Keyword', 'LastReview', 'ExpireDate', 'LeitnerBox', 'FailCount', 'PassCount'), array('col_escape' => array(0, 1, 1, 0, 0, 0, 0, 0)));
     $throttler->setTimeout();
     $this->getResponse()->setFileAttachmentHeaders('rtk_flashcards.csv');
     $this->setLayout(false);
     return $this->renderText($csvText);
 }
Пример #17
0
 /**
  * Add cards in Heisig order.
  * 
  * Selection should be a frame number to add up to,
  * or a number of cards to add "+10", filling in all missing cards in the RTK range.
  * 
  * @param string $selection  "56" (add up to 56), or "+20" (add 20 cards)
  * 
  * @return int   Number of cards in selection (also 0), or false if error
  */
 public function addHeisigRange($userId, $selection)
 {
     $this->itemIds = array();
     // get user's existing flashcard ids in RTK range
     $userCards = ReviewsPeer::getFlashcardIds($userId, 'rtk1+3');
     // map in an array, 1 means card exists, 0 it doesn't
     $inDeck = array();
     foreach ($userCards as $id) {
         $inDeck[(int) $id] = true;
     }
     // add a number of cards, or up to frame number, fill in the missing cards
     if (preg_match('/^\\+([0-9]+)$/', $selection, $matches)) {
         $range = $matches[1];
         if ($range < 1) {
             $this->request->setError('x', 'Invalid range of cards');
             return false;
         }
         for ($i = 1, $n = 0; $n < $range && $i <= rtkBook::MAXKANJI_VOL3; $i++) {
             if (!isset($inDeck[$i])) {
                 $this->itemIds[] = $i;
                 $n++;
             }
         }
     } else {
         $addTo = intval($selection);
         if (!rtkBook::isValidRtkFrameNum($addTo)) {
             $this->request->setError('x', sprintf('Invalid index number: "%s"', $selection));
             return false;
         }
         for ($i = 1; $i <= $addTo; $i++) {
             if (!isset($inDeck[$i])) {
                 $this->itemIds[] = $i;
             }
         }
     }
     return $this->getNumCards();
 }
Пример #18
0
		<div class="summary">
			<span class="total"><strong><?php 
echo $total_flashcards;
?>
</strong> kanji flashcards</span>&nbsp;
			( <?php 
echo link_to('browse detailed list', 'review/flashcardlist');
?>
 - <a href="@manage">manage flashcards</a> )
		</div>

		<div class="filterstop">

			<?php 
$links = array(array('ALL', '#', array('class' => 'uiFilterStd-all')), array('RTK1', '#', array('class' => 'uiFilterStd-rtk1')));
if (ReviewsPeer::getCountRtK3($_user->getUserId()) > 0) {
    $links[] = array('RTK3', '#', array('class' => 'uiFilterStd-rtk3'));
}
switch ($filter) {
    case 'rtk1':
        $active = 1;
        break;
    case 'rtk3':
        $active = 2;
        break;
    default:
        $active = 0;
        break;
}
echo ui_filter_std('Filter:', $links, array('id' => 'rtk-filter', 'active' => $active));
?>
Пример #19
0
 /**
  * Updates the flashcard count.
  * 
  * @param  int    $userId   User id.
  * 
  * @return boolean TRUE on success, FALSE on error.
  */
 public static function updateFlashcardCount($userId)
 {
     $data = array('fc_count' => ReviewsPeer::getFlashcardCount($userId));
     return self::getInstance()->updateCols($userId, $data);
 }
Пример #20
0
 /**
  * Retrieve multiple objects by pkey.
  *
  * @param      array $pks List of primary keys
  * @param      PropelPDO $con the connection to use
  * @throws     PropelException Any exceptions caught during processing will be
  *		 rethrown wrapped into a PropelException.
  */
 public static function retrieveByPKs($pks, PropelPDO $con = null)
 {
     if ($con === null) {
         $con = Propel::getConnection(ReviewsPeer::DATABASE_NAME, Propel::CONNECTION_READ);
     }
     $objs = null;
     if (empty($pks)) {
         $objs = array();
     } else {
         $criteria = new Criteria(ReviewsPeer::DATABASE_NAME);
         $criteria->add(ReviewsPeer::ID, $pks, Criteria::IN);
         $objs = ReviewsPeer::doSelect($criteria, $con);
     }
     return $objs;
 }
Пример #21
0
			<span class="btn">
				<?php 
    echo link_to('<img src="/images/2.0/study/review-small.gif" alt="Review" width="56" height="19" />', '@review', array('query_string' => 'type=relearned'));
    ?>
&nbsp;&nbsp;
				<?php 
    echo link_to('Clear', 'study/clear', array('class' => 'cancel'));
    ?>
			</span>
		</p>
<?php 
}
?>

<?php 
if ($restudyCount = ReviewsPeer::getRestudyKanjiCount($_user->getUserId())) {
    ?>
		<p class="set">
			<em><?php 
    echo $restudyCount;
    ?>
</em> to restudy<br/>
			<span class="btn">
				<?php 
    echo link_to('<img src="/images/2.0/study/review-small.gif" alt="Review" width="56" height="19" />', '@review', array('query_string' => 'box=1'));
    ?>
			</span>
		</p>

		<div class="failed-kanji">