public function postIndex()
 {
     // Parse the Job IDs
     $selected_classes = Input::get('classes');
     foreach (ClassJob::get_id_abbr_list(true) as $abbr => $id) {
         if (in_array($abbr, $selected_classes)) {
             $job_ids[] = $id;
         }
     }
     if (empty($job_ids)) {
         $job_ids[] = 1;
     }
     // All Leves
     $query = Leve::with(array('classjob', 'item', 'item.name', 'item.recipe', 'item.vendors'))->where('item_id', '>', 0)->orderBy('classjob_id')->orderBy('level')->orderBy('xp')->orderBy('gil');
     // Job IDs
     $query->whereIn('classjob_id', $job_ids);
     // Level Range
     $min = Input::get('min_level');
     $max = Input::get('max_level');
     // Invert if needed
     if ($min > $max) {
         list($max, $min) = array($min, $max);
     }
     $query->whereBetween('level', array($min, $max));
     // Triple Only
     if (Input::get('triple_only') == 'true') {
         $query->where('triple', 1);
     }
     // Types
     $query->whereIn('type', Input::get('types'));
     // Text Searches
     if (Input::get('leve_name')) {
         $query->where('name', 'like', '%' . Input::get('leve_name') . '%');
     }
     $leve_records = $query->remember(Config::get('site.cache_length'))->get();
     $location_search = strtolower(Input::get('leve_location'));
     $item_search = strtolower(Input::get('leve_item'));
     $rewards = LeveReward::with('item')->whereBetween('level', array($min, $max))->whereIn('classjob_id', $job_ids)->get();
     $leve_rewards = array();
     foreach ($leve_records as $k => $row) {
         if ($item_search && !preg_match('/' . $item_search . '/', strtolower($row->item->name->term))) {
             unset($leve_records[$k]);
             continue;
         }
         // TODO this can be moved into the query itself now, most likely
         if ($location_search) {
             if (!preg_match('/' . $location_search . '/', strtolower($row->location)) && !preg_match('/' . $location_search . '/', strtolower($row->major_location)) && !preg_match('/' . $location_search . '/', strtolower($row->minor_location))) {
                 unset($leve_records[$k]);
                 continue;
             }
         }
         foreach ($rewards as $reward) {
             if ($reward->classjob_id == $row->classjob_id && $reward->level == $row->level) {
                 $leve_rewards[$row->id][] = $reward;
             }
         }
     }
     return View::make('leve.rows')->with('leves', $leve_records)->with('leve_rewards', $leve_rewards);
 }
 public static function get_abbr_list($ids = array())
 {
     $all_jobs = ClassJob::with('abbr')->whereIn('id', $ids)->get();
     $return = array();
     foreach ($all_jobs as $job) {
         $return[] = $job->abbr->term;
     }
     return $return;
 }
 public function getIndex()
 {
     $account = Session::get('account');
     if (empty($account)) {
         return Redirect::to('/account/login');
     }
     $job_ids = Config::get('site.job_ids');
     return View::make('account.index')->with('crafting_job_list', ClassJob::with('name', 'en_abbr', 'en_name')->whereIn('id', $job_ids['crafting'])->get())->with('gathering_job_list', ClassJob::with('name', 'en_abbr', 'en_name')->whereIn('id', $job_ids['gathering'])->get())->with('melee_job_list', ClassJob::with('name', 'en_abbr', 'en_name')->whereIn('id', $job_ids['basic_melee'])->get())->with('magic_job_list', ClassJob::with('name', 'en_abbr', 'en_name')->whereIn('id', $job_ids['basic_magic'])->get());
 }
 public function postSearch()
 {
     $name = Input::get('name');
     $min = Input::get('min') ?: 1;
     $max = Input::get('max') ?: 50;
     $class = Input::get('class') ?: 'all';
     $per_page = Input::get('per_page') ?: 10;
     $sorting = Input::get('sorting') ?: 'name_asc';
     if (!in_array($per_page, array(10, 25, 50))) {
         $per_page = 10;
     }
     if (!is_numeric($min)) {
         $min = 1;
     }
     if (!is_numeric($max)) {
         $max = 50;
     }
     if ($min > $max) {
         list($max, $min) = array($min, $max);
     }
     $job_list = ClassJob::get_name_abbr_list();
     if ($class && $class != 'all') {
         $classjob = ClassJob::get_by_abbr($class);
     }
     $sorting = explode('_', $sorting);
     $order_by = 'name';
     $sort = 'asc';
     if (count($sorting) == 2) {
         // Only overwrite if need-be (i.e. don't test for "name" or "asc")
         if ($sorting[0] == 'level') {
             $order_by = $sorting[0];
         }
         if ($sorting[1] == 'desc') {
             $sort = $sorting[1];
         }
     }
     $query = Recipes::with('item', 'item.name')->select('*', 'recipes.id AS recipe_id', 'recipes.level AS level')->join('items AS i', 'i.id', '=', 'recipes.item_id')->join('translations AS t', 't.id', '=', 'i.name_' . Config::get('language'));
     $query->orderBy($order_by == 'name' ? 't.term' : 'recipes.' . $order_by, $sort);
     if ($name) {
         $query->whereHas('item', function ($query) use($name) {
             $query->whereHas('name', function ($query) use($name) {
                 $query->where('term', 'like', '%' . $name . '%');
             });
         });
     }
     if ($min && $max) {
         $query->whereBetween('recipes.level_view', array($min, $max));
     }
     if (isset($classjob)) {
         $query->where('recipes.classjob_id', $classjob->id);
     }
     $recipes = $query->paginate($per_page);
     View::share('list', $recipes);
     View::share('per_page', $per_page);
     $output = array('tbody' => View::make('recipes.results')->render(), 'tfoot' => View::make('recipes.results_footer')->render());
     return $output;
 }
 public function getIndex()
 {
     $job_ids = Config::get('site.job_ids.crafting');
     $job_ids[] = Config::get('site.job_ids.fishing');
     $type_to_icon = array('Field' => 'leaf', 'Courier' => 'envelope', 'Reverse Courier' => 'plane', 'Town' => 'home');
     // All Leves
     $all_leves = Leve::with(array('classjob', 'classjob.en_abbr', 'item', 'item.name', 'item.recipe', 'item.vendors'))->where('item_id', '>', 0)->orderBy('classjob_id')->orderBy('level')->orderBy('triple', 'desc')->orderBy('xp', 'desc')->orderBy('gil', 'desc')->get();
     $leves = array();
     foreach ($all_leves as $leve) {
         $leves[$leve->classjob->en_abbr->term][$leve->level][] = $leve;
     }
     $rewards = LeveReward::with('item')->orderBy('classjob_id')->orderBy('level')->orderBy('item_id')->orderBy('amount')->get();
     $leve_rewards = array();
     foreach ($rewards as $reward) {
         if ($reward->item_id) {
             $leve_rewards[$reward->classjob_id][$reward->level][$reward->item_id]['item'] = $reward->item;
             $leve_rewards[$reward->classjob_id][$reward->level][$reward->item_id]['amounts'][] = $reward->amount;
         }
     }
     return View::make('levequests.index')->with('crafting_job_list', ClassJob::with('name', 'en_name', 'en_abbr')->whereIn('id', $job_ids)->get())->with('crafting_job_ids', $job_ids)->with('leves', $leves)->with('rewards', $leve_rewards)->with('type_to_icon', $type_to_icon)->with('opening_level', 1)->with('opening_class', 'CRP');
 }
 public function getIndex()
 {
     // All Quests
     $quest_records = QuestItem::with('classjob', 'classjob.en_abbr', 'item', 'item.name', 'item.recipe')->orderBy('classjob_id')->orderBy('level')->orderBy('item_id')->get();
     $quests = array();
     foreach ($quest_records as $quest) {
         if (!isset($quests[$quest->classjob->en_abbr->term])) {
             $quests[$quest->classjob->en_abbr->term] = array();
         }
         if (empty($quest->item->recipe)) {
             var_dump($quest);
             exit;
         }
         foreach ($quest->item->recipe as $r) {
             if ($r->classjob_id == $quest->classjob_id) {
                 $quest->recipe = $r;
             }
         }
         $quests[$quest->classjob->en_abbr->term][] = $quest;
     }
     $job_ids = array_merge(Config::get('site.job_ids.crafting'), Config::get('site.job_ids.gathering'));
     return View::make('pages.quests')->with('quests', $quests)->with('job_ids', $job_ids)->with('job_list', ClassJob::with('name', 'en_abbr')->whereIn('id', $job_ids)->get());
 }
 public function getIndex()
 {
     // Get the list
     $list = Session::get('list', array());
     foreach ($list as $k => &$l) {
         // $l starts as the amount integer and we're transforming it to an array
         $l = array('amount' => $l, 'item' => Item::with(array('recipe' => function ($query) {
             $query->limit(1);
         }, 'name'))->find($k));
         if (count($l['item']->recipe) == 0) {
             unset($list[$k]);
         }
     }
     unset($l);
     $saved = array();
     if ($list) {
         foreach ($list as $id => $info) {
             $saved[] = $id . ',' . $info['amount'];
         }
     }
     $saved = implode(':', $saved);
     return View::make('pages.list')->with('active', 'list')->with('list', $list)->with('saved_link', $saved)->with('job_list', ClassJob::get_name_abbr_list());
 }
 public function postLoad()
 {
     $job = Input::get('job');
     $level = Input::get('level');
     $craftable_only = Input::get('craftable_only');
     $rewardable_too = Input::get('rewardable_too');
     // All Jobs
     $job_list = ClassJob::get_name_abbr_list();
     // Jobs are capital
     $desired_job = strtoupper($job);
     $job = ClassJob::get_by_abbr($desired_job);
     // What stats do the class like?
     $stat_ids_to_focus = Stat::get_ids(Stat::focus($job->abbr->term));
     View::share('job_list', $job_list);
     View::share('job', $job);
     View::share('stat_ids_to_focus', $stat_ids_to_focus);
     View::share('level', $level);
     $equipment = Item::calculate($job->id, $level, 0, $craftable_only, $rewardable_too);
     exit(json_encode($this->getOutput($equipment)));
 }
Example #9
0
 public static function calculate($job_id = 0, $level = 1, $range = 0, $craftable_only = TRUE, $rewardable_too = TRUE)
 {
     $cache_key = __METHOD__ . '|' . Config::get('language') . '|' . $job_id . ',' . $level . ',' . $range . ($craftable_only ? 'T' . ($rewardable_too ? 'T' : 'F') : 'F');
     // Does cache exist?  Return that instead
     if (Cache::has($cache_key)) {
         return Cache::get($cache_key);
     }
     // Get the job IDs
     $job = ClassJob::with('en_abbr')->find($job_id);
     $equipment_list = array_flip(Config::get('site.equipment_roles'));
     array_walk($equipment_list, function (&$i) {
         $i = array();
     });
     // Slot data
     $slots = Config::get('site.defined_slots');
     $slot_alias = Config::get('site.slot_alias');
     $slot_cannot_equip = Config::get('site.slot_cannot_equip');
     foreach ($slot_cannot_equip as &$sce) {
         foreach ($sce as &$ce) {
             $ce = $slots[$ce];
         }
     }
     unset($sce, $ce);
     // Make sure the slot avoids pieces with certain stats
     $stat_ids_to_avoid = Stat::get_ids(Stat::avoid($job->en_abbr->term));
     $stat_ids_to_focus = Stat::get_ids(Stat::focus($job->en_abbr->term));
     $boring_stat_ids = Stat::get_ids(Stat::boring());
     $advanced_stat_avoidance = Stat::advanced_avoidance($job->en_abbr->term);
     foreach ($advanced_stat_avoidance as &$ava) {
         // These are in a very specific order.
         // Keep that order in tact.
         list($a, $b) = explode(' w/o ', $ava);
         $ava[0] = Stat::get_ids(array($a))[0];
         $ava[1] = Stat::get_ids(array($b))[0];
     }
     unset($ava);
     // Get all items where:
     // Slot isn't zero
     // It's between the level & level - 10
     // The class can use it
     // craftable only?
     // rewardable?
     foreach ($slots as $slot_identifier => $slot_name) {
         $query = Item::with('name', 'baseparam', 'baseparam.name', 'vendors', 'recipe', 'recipe.classjob', 'recipe.classjob.name')->where('slot', $slot_identifier)->whereBetween('equip_level', array($level - 10, $level + $range))->whereHas('classjob', function ($query) use($job_id) {
             $query->where('classjob.id', $job_id);
         })->whereHas('baseparam', function ($query) use($stat_ids_to_focus) {
             $query->whereIn('baseparam.id', $stat_ids_to_focus);
         })->orderBy('items.equip_level', 'DESC')->orderBy('items.level', 'DESC')->limit(20);
         if ($craftable_only && $rewardable_too) {
             $query->where(function ($query) {
                 $query->whereHas('recipe', function ($query) {
                     $query->where('recipes.item_id', DB::raw('items.id'));
                 })->orWhere('items.achievable', '1')->orWhere('items.rewarded', '1');
             });
         } elseif ($craftable_only) {
             $query->whereHas('recipe', function ($query) {
                 $query->where('recipes.item_id', DB::raw('items.id'));
             });
         }
         $items = $query->remember(Config::get('site.cache_length'))->get();
         $slot = isset($slot_alias[$slot_identifier]) ? $slot_alias[$slot_identifier] : $slot_identifier;
         $role = $slots[$slot];
         foreach ($items as $item) {
             // Kick it to the curb because of attributes?
             // Compare the focused vs the avoids
             $focus = $avoid = 0;
             $param_count = array_fill(1, 100, 0);
             // 73 total stats, 100's pretty safe, not to mention we only really focus on the first dozen
             foreach ($item->baseparam as $param) {
                 $param_count[$param->id]++;
                 if (in_array($param->id, $stat_ids_to_avoid)) {
                     $avoid++;
                 } elseif (in_array($param->id, $stat_ids_to_focus)) {
                     $focus++;
                 }
             }
             if ($advanced_stat_avoidance) {
                 foreach ($advanced_stat_avoidance as $ava) {
                     // If the [0] stat exists, but the [1] stat doesn't, drop the piece completely
                     if ($param_count[$ava[0]] > 0 && $param_count[$ava[1]] == 0) {
                         $avoid += 10;
                     }
                 }
             }
             // Really sell that this should be avoided
             # echo '<strong>' . $item->name->term . ' [' . $item->id . ']</strong> for ' . $role . ' (' . $focus . ',' . $avoid . ')<br>';
             if ($avoid >= $focus || $focus == 0) {
                 continue;
             }
             // if ($item->name->term == 'Linen Cowl')
             // 	dd($item->name->term, $item->slot, $slot, $slot_cannot_equip, $slot_cannot_equip[$item->slot]);
             // Cannot equip attribute?
             if (isset($slot_cannot_equip[$item->slot])) {
                 $item->cannot_equip = implode(',', $slot_cannot_equip[$item->slot]);
             }
             $equipment_list[$role][] = $item;
             # echo '<strong>+ ' . $item->name->term . ' [' . $item->id . ']</strong> for ' . $role . '<br>';
         }
         unset($items);
     }
     $two_handed_weapon_ids = ItemUICategory::two_handed_weapon_ids();
     $leveled_equipment = array();
     // We now have a proper list, but now we need to widdle down further by ilvl
     foreach (range($level, $level + $range) as $l) {
         $leveled_equipment[$l] = array();
         foreach ($equipment_list as $role => $items) {
             $leveled_equipment[$l][$role] = array();
             $max_equip_level = 0;
             // Find max
             foreach ($items as $item) {
                 if ($item->equip_level <= $l && $item->equip_level > $max_equip_level) {
                     $max_equip_level = $item->equip_level;
                 }
             }
             // Drop lesser items
             // OR figure out cannot equip stuff for weapons
             foreach ($items as $key => $item) {
                 if ($item->equip_level == $max_equip_level) {
                     if (empty($item->cannot_equip) && in_array($item->itemuicategory_id, $two_handed_weapon_ids)) {
                         $item->cannot_equip = 'Off Hand';
                     }
                     //$item->cannot_equip = array_flip(Config::get('site.defined_slots'))['Off Hand'];
                     if (!isset($leveled_equipment[$l][$role][$item->level])) {
                         $leveled_equipment[$l][$role][$item->level] = array();
                     }
                     $leveled_equipment[$l][$role][$item->level][] = $item;
                 }
             }
             // Place highest ilvl first
             krsort($leveled_equipment[$l][$role]);
             // Re-key the list for good measure
             //$items = array_values($items);
             //$leveled_equipment[$l][$role] = $items;
         }
     }
     // We should mostly have a list of just single items now
     // Cache the results
     Cache::put($cache_key, $leveled_equipment, Config::get('site.cache_length'));
     return $leveled_equipment;
 }
 public function getGathering($my_class = '', $supported_classes = '', $min_level = 0, $max_level = 0)
 {
     $supported_classes = explode(',', $supported_classes);
     $show_quests = in_array($my_class, $supported_classes);
     if (empty($supported_classes)) {
         exit('No supported class selected... Todo: real error');
     }
     // TODO
     $all_classes = ClassJob::get_id_abbr_list();
     foreach ($supported_classes as $k => $v) {
         if (in_array($v, array_keys($all_classes))) {
             $supported_classes[$k] = $all_classes[$v];
         } else {
             unset($supported_classes[$k]);
         }
     }
     if (empty($supported_classes)) {
         exit('No supported class recognized...');
     }
     // TODO
     $jobs = ClassJob::with('name')->whereIn('id', $supported_classes)->get();
     foreach ($jobs as $k => $v) {
         $jobs[$k] = $v->name->term;
     }
     if ($my_class != 'BTL') {
         $job = ClassJob::get_by_abbr($my_class);
     } else {
         $job = $my_class;
     }
     if (empty($job)) {
         exit('No primary class recognized...');
     }
     // TODO
     $top_query = $inner_query = $join = $where = $union = $having = '';
     $parameters = array();
     DB::statement('SET SESSION group_concat_max_len=16384');
     if (in_array($my_class, array('MIN', 'BTN'))) {
         // Add Nodes
         $top_query .= "\n\t\t\t\t\t(\n\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\tCOUNT(*)\n\t\t\t\t\t\tFROM `cluster_items` AS `ci`\n\t\t\t\t\t\tJOIN `clusters` AS `c` ON `c`.`id` = `ci`.`cluster_id`\n\t\t\t\t\t\tWHERE `c`.`classjob_id` = ? AND `ci`.`item_id` = `x`.`item_id`\n\t\t\t\t\t) AS nodes,\n\t\t\t";
         $parameters[] = $job->id;
         $having = "HAVING nodes > 0";
     } else {
         // Battling or Fishing
         $join = "LEFT JOIN `cluster_items` AS `ci` ON `ci`.`item_id` = `i`.`id` " . 'LEFT JOIN `item_ui_category` AS `iuc` ON `iuc`.`id` = `i`.`itemuicategory_id` ' . 'LEFT JOIN `translations` AS `iuct` ON `iuct`.`id` = `iuc`.`name_en`';
         // FSH where the item is "seafood"
         // BTL where the item is not "seafood"
         $where = "AND `iuct`.`term` " . ($my_class == 'BTL' ? '!' : '') . "= 'Seafood'";
         $where .= " AND `ci`.`id` IS NULL";
     }
     $parameters[] = $min_level;
     $parameters[] = $max_level;
     $parameters = array_merge($parameters, $supported_classes);
     if ($my_class != 'BTL') {
         $union = "\n\t\t\t\t\tUNION\n\n\t\t\t\t\tSELECT\n\t\t\t\t\t\t`i`.`id`, t.term AS name, `i`.level, `i`.`min_price`, qi.amount AS amount, \n\t\t\t\t\t\tqi.level AS quest_level, qi.quality AS quest_quality\n\t\t\t\t\tFROM quest_items AS qi\n\t\t\t\t\tJOIN items AS i ON i.id = qi.item_id\n\t\t\t\t\tJOIN classjob AS j ON j.id = qi.classjob_id\n\t\t\t\t\tJOIN translations AS t ON t.id = i.name_" . Config::get('language') . "\n\t\t\t\t\tWHERE j.id = ?\n\t\t\t\t\t\tAND qi.level BETWEEN ? AND ?\n\t\t\t";
         $parameters[] = $job->id;
         $parameters[] = $min_level;
         $parameters[] = $max_level;
     }
     // TODO Caching
     $results = DB::select("\n\t\t\tSELECT x.*,\n\t\t\t\t" . $top_query . "\n\t\t\t\t(\n\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\tFROM `items_npcs_shops` AS `ins`\n\t\t\t\t\tWHERE `ins`.`item_id` = `x`.`item_id`\n\t\t\t\t) AS vendors, \n\t\t\t\t(\n\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\tFROM `npcs_items` AS `ni`\n\t\t\t\t\tWHERE `ni`.`item_id` = `x`.`item_id`\n\t\t\t\t) AS beasts\n\t\t\tFROM (\n\t\t\t\tSELECT \n\t\t\t\t\t`i`.`id` AS `item_id`, t.term AS name, `i`.level, `i`.`min_price`, SUM(cj.amount) AS amount,\n\t\t\t\t\tNULL AS quest_level, NULL AS quest_quality\n\t\t\t\tFROM `careers` AS `c`\n\t\t\t\tJOIN `items` AS `i` ON `i`.`id` = `c`.`identifier`\n\t\t\t\tJOIN `career_classjob` AS `cj` ON `cj`.`career_id` = `c`.`id`\n\t\t\t\tJOIN translations AS t ON t.id = i.name_" . Config::get('language') . "\n\t\t\t\t" . $join . "\n\t\t\t\tWHERE\n\t\t\t\t\t`c`.`type` = 'item'\n\t\t\t\t\tAND `c`.`level` BETWEEN ? AND ?\n\t\t\t\t\tAND `cj`.`classjob_id` in (" . str_pad('', count($supported_classes) * 2 - 1, '?,') . ")\n\t\t\t\t\t" . $where . "\n\t\t\t\tGROUP BY `c`.`identifier`\n\n\t\t\t\t" . $union . "\n\t\t\t\t\n\t\t\t\tORDER BY `item_id` ASC\n\t\t\t) AS x\n\t\t\t" . $having, $parameters);
     if ($my_class != 'BTL') {
         $quest_results = array();
         // Rip out Quest Entries
         foreach ($results as $k => $result) {
             if ($result->quest_level != NULL) {
                 $quest_results[] = $result;
                 unset($results[$k]);
             }
         }
         // Put them back in, either merge or insert
         if ($show_quests) {
             foreach ($quest_results as $quest_item) {
                 foreach ($results as $k => $result) {
                     if ($quest_item->item_id == $result->item_id) {
                         // Merge
                         $original_amount = $result->amount;
                         $quest_amount = $quest_item->amount;
                         $results[$k] = $quest_item;
                         $results[$k]->amount = $original_amount;
                         $results[$k]->quest_amount = $quest_amount;
                         continue 2;
                     }
                 }
                 // If a match was found it would have continued
                 // This means at this point we add it in straight up
                 $quest_item->quest_amount = $quest_item->amount;
                 $results[] = $quest_item;
             }
         }
         // Fishing doesn't have an ilvl...
         if ($my_class != 'FSH') {
             $sortable_results = array();
             foreach ($results as $row) {
                 $sortable_results[$row->level][] = $row;
             }
             ksort($sortable_results);
             $results = array();
             foreach ($sortable_results as $rows) {
                 foreach ($rows as $row) {
                     $results[] = $row;
                 }
             }
             unset($sortable_results);
         }
     }
     return View::make('career.items')->with(array('items' => $results, 'show_quests' => $show_quests, 'jobs' => $jobs, 'job' => $job, 'min_level' => $min_level, 'max_level' => $max_level));
 }
 public function getList()
 {
     // All Jobs
     $job_list = ClassJob::get_name_abbr_list();
     View::share('job_list', $job_list);
     $include_quests = TRUE;
     if (!Input::all()) {
         return Redirect::back();
     }
     // Get Options
     $options = explode(':', array_keys(Input::all())[0]);
     // Parse Options              						// Defaults
     $desired_job = isset($options[0]) ? $options[0] : 'CRP';
     $start = isset($options[1]) ? $options[1] : 1;
     $end = isset($options[2]) ? $options[2] : 5;
     $self_sufficient = isset($options[3]) ? $options[3] : 1;
     $misc_items = isset($options[4]) ? $options[4] : 0;
     $special = isset($options[5]) ? $options[5] : 0;
     $item_ids = $item_amounts = array();
     $top_level = TRUE;
     if ($desired_job == 'List') {
         $start = $end = null;
         $include_quests = FALSE;
         // Get the list
         $item_amounts = Session::get('list', array());
         $item_ids = array_keys($item_amounts);
         if (empty($item_ids)) {
             return Redirect::to('/list');
         }
         View::share('item_ids', $item_ids);
         View::share('item_amounts', $item_amounts);
         $top_level = $item_amounts;
     }
     if ($desired_job == 'Item') {
         $item_id = $special;
         $start = $end = null;
         $include_quests = FALSE;
         // Get the list
         $item_amounts = array($item_id => 1);
         $item_ids = array_keys($item_amounts);
         if (empty($item_ids)) {
             return Redirect::to('/list');
         }
         View::share('item_ids', $item_ids);
         View::share('item_amounts', $item_amounts);
         View::share('item_special', true);
         $top_level = $item_amounts;
     }
     if (!$item_ids) {
         // Jobs are capital
         $desired_job = strtoupper($desired_job);
         // Make sure it's a real job, jobs might be multiple
         $job = array();
         foreach (explode(',', $desired_job) as $ds) {
             $job[] = ClassJob::get_by_abbr($ds);
         }
         // If the job isn't real, error out
         if (!isset($job[0])) {
             // Check for DOL quests
             $quests = array();
             foreach (array('MIN', 'BTN', 'FSH') as $job) {
                 $job = ClassJob::get_by_abbr($job);
                 $quests[$job] = QuestItem::where('classjob_id', $job->id)->orderBy('level')->with('item')->get();
             }
             return View::make('crafting')->with('error', TRUE)->with('quests', $quests);
         }
         $job_ids = array();
         foreach ($job as $j) {
             $job_ids[] = $j->id;
         }
         $full_name_desired_job = false;
         if (count($job) == 1) {
             $job = $job[0];
             $full_name_desired_job = $job->name->term;
         }
         // Starting maximum of 1
         if ($start < 0) {
             $start = 1;
         }
         if ($start > $end) {
             $end = $start;
         }
         if ($end - $start > 9) {
             $end = $start + 9;
         }
         // Check for quests
         $quest_items = QuestItem::with('classjob', 'classjob.abbr')->whereBetween('level', array($start, $end))->whereIn('classjob_id', $job_ids)->orderBy('level')->with('item')->get();
         View::share(array('job' => $job, 'start' => $start, 'end' => $end, 'quest_items' => $quest_items, 'desired_job' => $desired_job, 'full_name_desired_job' => $full_name_desired_job));
     }
     // Gather Recipes and Reagents
     $query = Recipes::with('name', 'classjob', 'classjob.name', 'classjob.abbr', 'item', 'item.name', 'item.quest', 'item.leve', 'item.vendors', 'item.beasts', 'item.clusters', 'item.clusters.classjob', 'item.clusters.classjob.abbr', 'reagents', 'reagents.vendors', 'reagents.beasts', 'reagents.clusters', 'reagents.clusters.classjob', 'reagents.clusters.classjob.abbr', 'reagents.recipe', 'reagents.recipe.name', 'reagents.recipe.item', 'reagents.recipe.item.name', 'reagents.recipe.item.vendors', 'reagents.recipe.item.beasts', 'reagents.recipe.item.clusters', 'reagents.recipe.item.clusters.classjob', 'reagents.recipe.item.clusters.classjob.abbr', 'reagents.recipe.classjob', 'reagents.recipe.classjob.abbr')->groupBy('recipes.item_id')->orderBy('rank');
     if ($misc_items == 0 && $desired_job != 'List') {
         $query->whereHas('item', function ($query) {
             $query->whereNotIn('itemcategory_id', array(14, 15))->where(function ($query) {
                 $query->where('itemcategory_id', '!=', 16)->where('itemuicategory_id', '!=', 63);
                 // Other
             });
         });
     }
     if ($item_ids) {
         $query->whereIn('recipes.item_id', $item_ids);
     } else {
         $query->whereHas('classjob', function ($query) use($job_ids) {
             $query->whereIn('classjob.id', $job_ids);
         })->whereBetween('level', array($start, $end));
     }
     $recipes = $query->remember(Config::get('site.cache_length'))->get();
     // Fix the amount of the top level to be evenly divisible by the amount the recipe yields
     if (is_array($top_level)) {
         foreach ($recipes as $recipe) {
             $tl_item =& $top_level[$recipe->item_id];
             // If they're not evently divisible
             if ($tl_item % $recipe->yields != 0) {
                 // Make it so
                 $tl_item = ceil($tl_item / $recipe->yields) * $recipe->yields;
             }
         }
         unset($tl_item);
         View::share('item_amounts', $top_level);
     }
     $reagent_list = $this->_reagents($recipes, $self_sufficient, 1, $include_quests, $top_level);
     // Look through the list.  Is there something we're already crafting?
     // Subtract what's being made from needed reagents.
     //  Example, culinary 11 to 15, you need olive oil for Parsnip Salad (lvl 13)
     //   But you make 3 olive oil at level 11.  We don't want them crafting another olive oil.
     foreach ($recipes as $recipe) {
         if (!isset($reagent_list[$recipe->item_id])) {
             continue;
         }
         $reagent_list[$recipe->item_id]['both_list_warning'] = TRUE;
         $reagent_list[$recipe->item_id]['make_this_many'] += 1;
     }
     // Look through the reagent list, make sure the reagents are evently divisible by what they yield
     foreach ($reagent_list as &$reagent) {
         // If they're not evently divisible
         if ($reagent['make_this_many'] % $reagent['yields'] != 0) {
             // Make it so
             $reagent['make_this_many'] = ceil($reagent['make_this_many'] / $reagent['yields']) * $reagent['yields'];
         }
     }
     unset($reagent);
     // Let's sort them further, group them by..
     // Gathered, Then by Level
     // Other (likely mob drops)
     // Crafted, Then by level
     // Bought, by price
     $sorted_reagent_list = array('Gathered' => array(), 'Bought' => array(), 'Other' => array(), 'Pre-Requisite Crafting' => array(), 'Crafting List' => array());
     $gathering_class_abbreviations = ClassJob::get_abbr_list(Config::get('site.job_ids.gathering'));
     foreach ($reagent_list as $reagent) {
         $section = 'Other';
         $level = 0;
         // Section
         if (in_array($reagent['self_sufficient'], $gathering_class_abbreviations)) {
             $section = 'Gathered';
             $level = $reagent['item']->level;
         } elseif ($reagent['self_sufficient']) {
             $section = 'Pre-Requisite Crafting';
             if (!isset($reagent['item']->recipe[0])) {
                 dd($reagent['item']);
             }
             $level = $reagent['item']->recipe[0]->level;
         } elseif (count($reagent['item']->vendors)) {
             $section = 'Bought';
             $level = $reagent['item']->min_price;
         }
         if (!isset($sorted_reagent_list[$section][$level])) {
             $sorted_reagent_list[$section][$level] = array();
         }
         $sorted_reagent_list[$section][$level][$reagent['item']->id] = $reagent;
         ksort($sorted_reagent_list[$section][$level]);
     }
     foreach ($sorted_reagent_list as $section => $list) {
         ksort($sorted_reagent_list[$section]);
     }
     // Sort the pre-requisite crafting by rank
     // We don't need to sort them by level, just make sure it's in the proper structure
     // The keys don't matter either
     $prc =& $sorted_reagent_list['Pre-Requisite Crafting'];
     $new_prc = array('1' => array());
     foreach ($prc as $vals) {
         foreach ($vals as $v) {
             $new_prc['1'][] = $v;
         }
     }
     // Sort them by rank first
     usort($new_prc['1'], function ($a, $b) {
         return $a['item']->rank - $b['item']->rank;
     });
     // Then by classjob
     usort($new_prc['1'], function ($a, $b) {
         return $a['item']->recipe[0]->classjob_id - $b['item']->recipe[0]->classjob_id;
     });
     $prc = $new_prc;
     return View::make('crafting.list')->with(array('recipes' => $recipes, 'reagent_list' => $sorted_reagent_list, 'self_sufficient' => $self_sufficient, 'misc_items' => $misc_items, 'include_quests' => $include_quests));
 }