static function parse_paper_options(PaperInfo $prow, $all)
 {
     $optionIds = get($prow, "optionIds");
     if ($optionIds === "") {
         return [];
     }
     $optsel = array();
     if ($optionIds !== null) {
         preg_match_all('/(\\d+)#(\\d+)/', $optionIds, $m);
         for ($i = 0; $i < count($m[1]); ++$i) {
             arrayappend($optsel[$m[1][$i]], (int) $m[2][$i]);
         }
         $optdata = null;
     } else {
         $optdata = self::load_optdata($prow->paperId);
         foreach ($optdata as $k => $v) {
             $dot = strpos($k, ".");
             arrayappend($optsel[substr($k, 0, $dot)], (int) substr($k, $dot + 1));
         }
     }
     $option_array = array();
     foreach ($optsel as $oid => $ovalues) {
         $o = PaperOption::find($oid);
         if (!$o && !$all) {
             continue;
         }
         $needs_data = !$o || $o->needs_data();
         if ($needs_data && !$optdata) {
             $optdata = self::load_optdata($prow->paperId);
         }
         $odata = [];
         if ($needs_data) {
             foreach ($ovalues as $v) {
                 $odata[] = $optdata[$oid . "." . $v];
             }
         }
         $option_array[$oid] = new PaperOptionValue($oid, $o, $ovalues, $odata);
     }
     uasort($option_array, function ($a, $b) {
         if ($a->option && $b->option) {
             return PaperOption::compare($a->option, $b->option);
         } else {
             if ($a->option || $b->option) {
                 return $a->option ? -1 : 1;
             } else {
                 return $a->id - $b->id;
             }
         }
     });
     return $option_array;
 }