Index: trunk/extensions/ProofreadPage/ProofreadPage.i18n.php |
— | — | @@ -8,6 +8,7 @@ |
9 | 9 | $messages = array(); |
10 | 10 | |
11 | 11 | $messages['en'] = array( |
| 12 | + 'proofreadpages' => 'List of index pages', |
12 | 13 | 'proofreadpage_desc' => 'Allow easy comparison of text to the original scan', |
13 | 14 | 'proofreadpage_namespace' => 'Page', |
14 | 15 | 'proofreadpage_index_namespace' => 'Index', |
Index: trunk/extensions/ProofreadPage/ProofreadPage.php |
— | — | @@ -1,5 +1,11 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +/* |
| 5 | + todo : |
| 6 | + - check for dupes in index page : when index is saved |
| 7 | + - check unicity of the index page : when index is saved too |
| 8 | +*/ |
| 9 | + |
4 | 10 | if ( !defined( 'MEDIAWIKI' ) ) { |
5 | 11 | die( "ProofreadPage extension\n" ); |
6 | 12 | } |
— | — | @@ -15,7 +21,17 @@ |
16 | 22 | $wgHooks['ArticleSaveComplete'][] = 'pr_articleSaveComplete'; |
17 | 23 | $wgHooks['ArticleDelete'][] = 'pr_articleDelete'; |
18 | 24 | $wgHooks['EditFormPreloadText'][] = 'pr_preloadText'; |
| 25 | +$wgHooks['ArticlePurge'][] = 'pr_articlePurge'; |
| 26 | +$wgHooks['SpecialMovepageAfterMove'][] = 'pr_movePage'; |
| 27 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'pr_schema_update'; |
19 | 28 | |
| 29 | + |
| 30 | +# special page |
| 31 | +$wgAutoloadClasses['ProofreadPages'] = $dir . 'SpecialProofreadPages.php'; |
| 32 | +$wgSpecialPages['ProofreadPages'] = 'ProofreadPages'; |
| 33 | +$wgSpecialPageGroups['ProofreadPages'] = 'pages'; |
| 34 | + |
| 35 | + |
20 | 36 | # Allows for extracting text from djvu files. To enable, set to 'djvutxt' or similar |
21 | 37 | $wgDjvutxt = null; |
22 | 38 | |
— | — | @@ -37,6 +53,16 @@ |
38 | 54 | |
39 | 55 | $wgExtensionFunctions[] = "pr_main"; |
40 | 56 | |
| 57 | + |
| 58 | +function pr_schema_update() { |
| 59 | + global $wgExtNewTables; |
| 60 | + $base = dirname(__FILE__); |
| 61 | + $wgExtNewTables[] = array( 'pr_index', "$base/ProofreadPage.sql" ); |
| 62 | + return true; |
| 63 | +} |
| 64 | + |
| 65 | + |
| 66 | + |
41 | 67 | function pr_main() { |
42 | 68 | global $wgParser; |
43 | 69 | global $pr_page_namespace, $pr_index_namespace; |
— | — | @@ -175,7 +201,7 @@ |
176 | 202 | $attributes["pagenum"] = $pagenum; |
177 | 203 | } else { |
178 | 204 | for( $i=0; $i<count( $links[1] ); $i++) { |
179 | | - $a_title = Title::newFromText( $links[1][$i] ); |
| 205 | + $a_title = Title::newFromText( $pr_page_namespace.":".$links[1][$i] ); |
180 | 206 | if(!$a_title) continue; |
181 | 207 | if( $a_title->getPrefixedText() == $title->getPrefixedText() ) { |
182 | 208 | $attributes["pagenum"] = $links[3][$i]; |
— | — | @@ -183,10 +209,10 @@ |
184 | 210 | } |
185 | 211 | } |
186 | 212 | if( ($i>0) && ($i<count($links[1])) ){ |
187 | | - $prev_title = Title::newFromText( $links[1][$i-1] ); |
| 213 | + $prev_title = Title::newFromText( $pr_page_namespace.":".$links[1][$i-1] ); |
188 | 214 | } |
189 | 215 | if( ($i>=0) && ($i+1<count($links[1])) ){ |
190 | | - $next_title = Title::newFromText( $links[1][$i+1] ); |
| 216 | + $next_title = Title::newFromText( $pr_page_namespace.":".$links[1][$i+1] ); |
191 | 217 | } |
192 | 218 | if($prev_title) $prev_url = $prev_title->getFullURL(); |
193 | 219 | if($next_title) $next_url = $next_title->getFullURL(); |
— | — | @@ -233,7 +259,7 @@ |
234 | 260 | $links = null; |
235 | 261 | } else { |
236 | 262 | $params = null; |
237 | | - $tag_pattern = "/\[\[($pr_page_namespace:.*?)(\|(.*?)|)\]\]/i"; |
| 263 | + $tag_pattern = "/\[\[$pr_page_namespace:(.*?)(\|(.*?)|)\]\]/i"; |
238 | 264 | preg_match_all( $tag_pattern, $text, $links, PREG_PATTERN_ORDER ); |
239 | 265 | } |
240 | 266 | |
— | — | @@ -730,12 +756,13 @@ |
731 | 757 | for( $i=0; $i<count( $links[1] ); $i++) { |
732 | 758 | $text = $links[1][$i]; |
733 | 759 | $pagenum = $links[3][$i]; |
734 | | - if($text == $pr_page_namespace.":".$from ) $adding = true; |
| 760 | + if($text == $from ) $adding = true; |
735 | 761 | if($adding){ |
736 | | - $out.= "<span>{{:MediaWiki:Proofreadpage_pagenum_template|page=".$text."|num=$pagenum}}</span>"; |
737 | | - $out.= "{{:".$text."}}"; |
| 762 | + $out.= "<span>{{:MediaWiki:Proofreadpage_pagenum_template|page=" |
| 763 | + .$pr_page_namespace.":".$text."|num=$pagenum}}</span>"; |
| 764 | + $out.= "{{:".$pr_page_namespace.":".$text."}}"; |
738 | 765 | } |
739 | | - if($text == $pr_page_namespace.":".$to ) $adding = false; |
| 766 | + if($text == $to ) $adding = false; |
740 | 767 | } |
741 | 768 | $out = $wgParser->recursiveTagParse($out); |
742 | 769 | } |
— | — | @@ -824,18 +851,30 @@ |
825 | 852 | |
826 | 853 | |
827 | 854 | /* |
828 | | - * if I delete a page, I need to update the index |
| 855 | + * if I delete a page, I need to update the index table |
| 856 | + * if I delete an index page too... |
829 | 857 | */ |
830 | 858 | function pr_articleDelete( $article ) { |
831 | 859 | global $pr_page_namespace, $pr_index_namespace; |
832 | 860 | |
833 | 861 | $title = $article->mTitle; |
834 | 862 | |
| 863 | + if ( preg_match( "/^$pr_index_namespace:(.*)$/", $title->getPrefixedText() ) ) { |
| 864 | + $id = $article->getID(); |
| 865 | + $pr_index = $dbw->tableName( 'pr_index' ); |
| 866 | + $dbw = wfGetDB( DB_MASTER ); |
| 867 | + $dbw->query ("DELETE FROM $pr_index WHERE pr_page_id=$id"); |
| 868 | + $dbw->commit(); |
| 869 | + return true; |
| 870 | + } |
| 871 | + |
835 | 872 | if ( preg_match( "/^$pr_page_namespace:(.*)$/", $title->getPrefixedText() ) ) { |
836 | 873 | pr_load_index( $title ); |
837 | 874 | if( $title->pr_index_title ) { |
838 | 875 | $index_title = Title::newFromText( $title->pr_index_title ); |
839 | 876 | $index_title->invalidateCache(); |
| 877 | + $index = new Article( $index_title ); |
| 878 | + if( $index ) pr_update_pr_index( $index, $title->getDBKey() ); |
840 | 879 | } |
841 | 880 | return true; |
842 | 881 | } |
— | — | @@ -850,11 +889,19 @@ |
851 | 890 | |
852 | 891 | $title = $article->mTitle; |
853 | 892 | |
| 893 | + //if it's an index, update pr_index table |
| 894 | + if ( preg_match( "/^$pr_index_namespace:(.*)$/", $title->getPrefixedText(), $m ) ) { |
| 895 | + pr_update_pr_index( $article ); |
| 896 | + return true; |
| 897 | + } |
| 898 | + |
854 | 899 | //return if it is not a page |
855 | 900 | if ( ! preg_match( "/^$pr_page_namespace:(.*)$/", $title->getPrefixedText() ) ) { |
856 | 901 | return true; |
857 | 902 | } |
858 | 903 | |
| 904 | + $dbw = wfGetDB( DB_MASTER ); |
| 905 | + |
859 | 906 | /* check if there is an index */ |
860 | 907 | if ( !isset( $title->pr_index_title ) ) { |
861 | 908 | pr_load_index( $title ); |
— | — | @@ -871,6 +918,46 @@ |
872 | 919 | $index_title->invalidateCache(); |
873 | 920 | } |
874 | 921 | |
| 922 | + /* |
| 923 | + * update pr_index iteratively |
| 924 | + */ |
| 925 | + $index = new Article( $index_title ); |
| 926 | + $index_id = $index->getID(); |
| 927 | + $dbr = wfGetDB( DB_SLAVE ); |
| 928 | + $pr_index = $dbr->tableName( 'pr_index' ); |
| 929 | + $query = "SELECT * FROM $pr_index WHERE pr_page_id=".$index_id; |
| 930 | + $res = $dbr->query( $query, __METHOD__ ); |
| 931 | + if( $x = $dbr->fetchObject( $res ) ) { |
| 932 | + $n = $x->pr_count ; |
| 933 | + $n0 = $x->pr_q0 ; |
| 934 | + $n1 = $x->pr_q1 ; |
| 935 | + $n2 = $x->pr_q2 ; |
| 936 | + $n3 = $x->pr_q3 ; |
| 937 | + $n4 = $x->pr_q4 ; |
| 938 | + |
| 939 | + switch( $article->new_q ) { |
| 940 | + case 0: $n0 = $n0 + 1; break; |
| 941 | + case 1: $n1 = $n1 + 1; break; |
| 942 | + case 2: $n2 = $n2 + 1; break; |
| 943 | + case 3: $n3 = $n3 + 1; break; |
| 944 | + case 4: $n4 = $n4 + 1; break; |
| 945 | + } |
| 946 | + |
| 947 | + switch( $article->old_q ) { |
| 948 | + case 0: $n0 = $n0 - 1; break; |
| 949 | + case 1: $n1 = $n1 - 1; break; |
| 950 | + case 2: $n2 = $n2 - 1; break; |
| 951 | + case 3: $n3 = $n3 - 1; break; |
| 952 | + case 4: $n4 = $n4 - 1; break; |
| 953 | + } |
| 954 | + |
| 955 | + $query = "REPLACE INTO $pr_index (pr_page_id, pr_count, pr_q0, pr_q1, pr_q2, pr_q3, pr_q4) VALUES ({$index_id},$n,$n0,$n1,$n2,$n3,$n4)"; |
| 956 | + $dbw->query ( $query ); |
| 957 | + $dbw->commit(); |
| 958 | + |
| 959 | + } |
| 960 | + $dbr->freeResult( $res ); |
| 961 | + |
875 | 962 | return true; |
876 | 963 | } |
877 | 964 | |
— | — | @@ -901,3 +988,133 @@ |
902 | 989 | |
903 | 990 | |
904 | 991 | |
| 992 | +function pr_movePage( $form, $ot, $nt ) { |
| 993 | + global $pr_page_namespace, $pr_index_namespace; |
| 994 | + |
| 995 | + if ( preg_match( "/^$pr_page_namespace:(.*)$/", $ot->getPrefixedText() ) ) { |
| 996 | + pr_load_index( $ot ); |
| 997 | + if( $ot->pr_index_title ) { |
| 998 | + $index_title = Title::newFromText( $ot->pr_index_title ); |
| 999 | + $index_title->invalidateCache(); |
| 1000 | + $index = new Article( $index_title ); |
| 1001 | + if( $index ) pr_update_pr_index( $index ); |
| 1002 | + } |
| 1003 | + return true; |
| 1004 | + } |
| 1005 | + |
| 1006 | + if ( preg_match( "/^$pr_page_namespace:(.*)$/", $nt->getPrefixedText() ) ) { |
| 1007 | + pr_load_index( $nt ); |
| 1008 | + if( $nt->pr_index_title && ($nt->pr_index_title!=$ot->pr_index_title) ) { |
| 1009 | + $index_title = Title::newFromText( $nt->pr_index_title ); |
| 1010 | + $index_title->invalidateCache(); |
| 1011 | + $index = new Article( $index_title ); |
| 1012 | + if( $index ) pr_update_pr_index( $index ); |
| 1013 | + } |
| 1014 | + return true; |
| 1015 | + } |
| 1016 | + return true; |
| 1017 | +} |
| 1018 | + |
| 1019 | + |
| 1020 | +/* |
| 1021 | + * When an index page is created or purged, recompute pr_index values |
| 1022 | + */ |
| 1023 | +function pr_articlePurge( $article ) { |
| 1024 | + global $pr_page_namespace, $pr_index_namespace; |
| 1025 | + |
| 1026 | + $title = $article->mTitle; |
| 1027 | + if ( preg_match( "/^$pr_index_namespace:(.*)$/", $title->getPrefixedText() ) ) { |
| 1028 | + pr_update_pr_index( $article ); |
| 1029 | + return true; |
| 1030 | + } |
| 1031 | + return true; |
| 1032 | +} |
| 1033 | + |
| 1034 | + |
| 1035 | + |
| 1036 | +/* |
| 1037 | + * update the pr_index entry of an article |
| 1038 | + */ |
| 1039 | +function pr_update_pr_index( $index, $deletedpage=null ) { |
| 1040 | + global $pr_page_namespace, $pr_index_namespace; |
| 1041 | + |
| 1042 | + $index_title = $index->mTitle; |
| 1043 | + $index_id = $index->getID(); |
| 1044 | + |
| 1045 | + //read the list of pages |
| 1046 | + $pages = array(); |
| 1047 | + list( $links, $params, $attributes ) = pr_parse_index( $index_title ); |
| 1048 | + if( $links==null ) { |
| 1049 | + $imageTitle = Title::makeTitleSafe( NS_IMAGE, $index_title->getText() ); |
| 1050 | + if ( $imageTitle ) { |
| 1051 | + $image = wfFindFile( $imageTitle ); |
| 1052 | + if ( $image && $image->isMultiPage() && $image->pageCount() ) { |
| 1053 | + $n = $image->pageCount(); |
| 1054 | + for ( $i = 1; $i <= $n; $i++ ) { |
| 1055 | + $page = $index_title->getDBKey().'/'.$i; |
| 1056 | + if($page != $deletedpage) array_push( $pages, $page ); |
| 1057 | + } |
| 1058 | + } |
| 1059 | + } |
| 1060 | + } else { |
| 1061 | + $n = count($links[1]); |
| 1062 | + for ( $i = 0; $i < $n; $i++ ) { |
| 1063 | + $page = str_replace( ' ' , '_' , $links[1][$i] ); |
| 1064 | + if($page != $deletedpage) array_push( $pages, $page ); |
| 1065 | + } |
| 1066 | + } |
| 1067 | + $n0 = $n1 = $n2 = $n3 = $n4 = 0; |
| 1068 | + |
| 1069 | + $dbr = wfGetDB( DB_SLAVE ); |
| 1070 | + $catlinks = $dbr->tableName( 'categorylinks' ); |
| 1071 | + $page = $dbr->tableName( 'page' ); |
| 1072 | + $pagelist = "'".implode( "', '", $pages)."'"; |
| 1073 | + $page_ns_index = MWNamespace::getCanonicalIndex( strtolower( $pr_page_namespace ) ); |
| 1074 | + $query = "SELECT COUNT(page_id) AS count FROM $page LEFT JOIN $catlinks ON cl_from=page_id WHERE cl_to='###' AND page_namespace=$page_ns_index AND page_title IN ( $pagelist )" ; |
| 1075 | + |
| 1076 | + $q0 = str_replace( ' ' , '_' , wfMsgForContent( 'proofreadpage_quality0_category' ) ); |
| 1077 | + $res = $dbr->query( str_replace( '###', $q0, $query) , __METHOD__ ); |
| 1078 | + if( $res && $dbr->numRows( $res ) > 0 ) { |
| 1079 | + $row = $dbr->fetchObject( $res ); |
| 1080 | + $n0 = $row->count; |
| 1081 | + $dbr->freeResult( $res ); |
| 1082 | + } |
| 1083 | + |
| 1084 | + $q1 = str_replace( ' ' , '_' , wfMsgForContent( 'proofreadpage_quality1_category' ) ); |
| 1085 | + $res = $dbr->query( str_replace( '###', $q1, $query) , __METHOD__ ); |
| 1086 | + if( $res && $dbr->numRows( $res ) > 0 ) { |
| 1087 | + $row = $dbr->fetchObject( $res ); |
| 1088 | + $n1 = $row->count; |
| 1089 | + $dbr->freeResult( $res ); |
| 1090 | + } |
| 1091 | + |
| 1092 | + $q2 = str_replace( ' ' , '_' , wfMsgForContent( 'proofreadpage_quality2_category' ) ); |
| 1093 | + $res = $dbr->query( str_replace( '###', $q2, $query) , __METHOD__ ); |
| 1094 | + if( $res && $dbr->numRows( $res ) > 0 ) { |
| 1095 | + $row = $dbr->fetchObject( $res ); |
| 1096 | + $n2 = $row->count; |
| 1097 | + $dbr->freeResult( $res ); |
| 1098 | + } |
| 1099 | + |
| 1100 | + $q3 = str_replace( ' ' , '_' , wfMsgForContent( 'proofreadpage_quality3_category' ) ); |
| 1101 | + $res = $dbr->query( str_replace( '###', $q3, $query) , __METHOD__ ); |
| 1102 | + if( $res && $dbr->numRows( $res ) > 0 ) { |
| 1103 | + $row = $dbr->fetchObject( $res ); |
| 1104 | + $n3 = $row->count; |
| 1105 | + $dbr->freeResult( $res ); |
| 1106 | + } |
| 1107 | + |
| 1108 | + $q4 = str_replace( ' ' , '_' , wfMsgForContent( 'proofreadpage_quality4_category' ) ); |
| 1109 | + $res = $dbr->query( str_replace( '###', $q4, $query) , __METHOD__ ); |
| 1110 | + if( $res && $dbr->numRows( $res ) > 0 ) { |
| 1111 | + $row = $dbr->fetchObject( $res ); |
| 1112 | + $n4 = $row->count; |
| 1113 | + $dbr->freeResult( $res ); |
| 1114 | + } |
| 1115 | + |
| 1116 | + $dbw = wfGetDB( DB_MASTER ); |
| 1117 | + $pr_index = $dbw->tableName( 'pr_index' ); |
| 1118 | + $query = "REPLACE INTO $pr_index (pr_page_id, pr_count, pr_q0, pr_q1, pr_q2, pr_q3, pr_q4) VALUES ({$index_id},$n,$n0,$n1,$n2,$n3,$n4)"; |
| 1119 | + $dbw->query ( $query ); |
| 1120 | + $dbw->commit(); |
| 1121 | +} |
Index: trunk/extensions/ProofreadPage/SpecialProofreadPages.php |
— | — | @@ -0,0 +1,106 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * @file |
| 5 | + * @ingroup SpecialPage |
| 6 | + */ |
| 7 | + |
| 8 | + |
| 9 | +if ( !defined( 'MEDIAWIKI' ) ) die( 1 ); |
| 10 | +global $wgHooks, $IP; |
| 11 | +require_once "$IP/includes/QueryPage.php"; |
| 12 | + |
| 13 | + |
| 14 | +class ProofreadPages extends SpecialPage { |
| 15 | + |
| 16 | + function ProofreadPages() { |
| 17 | + SpecialPage::SpecialPage( 'ProofreadPages' ); |
| 18 | + } |
| 19 | + |
| 20 | + function execute( $parameters ) { |
| 21 | + $this->setHeaders(); |
| 22 | + list( $limit, $offset ) = wfCheckLimits(); |
| 23 | + |
| 24 | + $cnl = new ProofreadPagesQuery(); |
| 25 | + $cnl->doQuery( $offset, $limit ); |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +class ProofreadPagesQuery extends QueryPage { |
| 32 | + |
| 33 | + function getName() { |
| 34 | + return 'ProofreadPagesQuery'; |
| 35 | + } |
| 36 | + |
| 37 | + function isExpensive() { |
| 38 | + return false; |
| 39 | + } |
| 40 | + |
| 41 | + function isSyndicated() { |
| 42 | + return false; |
| 43 | + } |
| 44 | + |
| 45 | + function getSQL() { |
| 46 | + $dbr = wfGetDB( DB_SLAVE ); |
| 47 | + $page = $dbr->tableName( 'page' ); |
| 48 | + $pr_index = $dbr->tableName( 'pr_index' ); |
| 49 | + $name = $dbr->addQuotes( $this->getName() ); |
| 50 | + |
| 51 | + return |
| 52 | + "SELECT pr_page_id as title, |
| 53 | + page_title as title, |
| 54 | + pr_count, |
| 55 | + pr_q0, |
| 56 | + pr_q1, |
| 57 | + pr_q2, |
| 58 | + pr_q3, |
| 59 | + pr_q4 |
| 60 | + FROM $pr_index |
| 61 | + LEFT JOIN $page ON page_id = pr_page_id"; |
| 62 | + } |
| 63 | + |
| 64 | + function getOrder() { |
| 65 | + return ' ORDER BY 2*pr_q4+pr_q3 ' . |
| 66 | + ($this->sortDescending() ? 'DESC' : ''); |
| 67 | + } |
| 68 | + |
| 69 | + function sortDescending() { |
| 70 | + return true; |
| 71 | + } |
| 72 | + |
| 73 | + function formatResult( $skin, $result ) { |
| 74 | + global $wgLang, $wgContLang; |
| 75 | + global $pr_index_namespace; |
| 76 | + |
| 77 | + $dm = $wgContLang->getDirMark(); |
| 78 | + |
| 79 | + $title = Title::newFromText( $pr_index_namespace.":".$result->title ); |
| 80 | + |
| 81 | + if ( !$title ) { |
| 82 | + return '<!-- Invalid title ' . htmlspecialchars( $pr_index_namespace.":".$result->title ). '-->'; |
| 83 | + } |
| 84 | + $plink = $this->isCached() |
| 85 | + ? $skin->makeLinkObj( $title , $title->getText() ) |
| 86 | + : $skin->makeKnownLinkObj( $title , $title->getText() ); |
| 87 | + $size = "[".$result->pr_count." pages] "; |
| 88 | + $q0 = $result->pr_q0; |
| 89 | + $q1 = $result->pr_q1; |
| 90 | + $q2 = $result->pr_q2; |
| 91 | + $q3 = $result->pr_q3; |
| 92 | + $q4 = $result->pr_q4; |
| 93 | + |
| 94 | + $table = "<table style=\"display:inline;line-height:100%;vertical-align:middle;\" border=0 cellpadding=0 cellspacing=0 > |
| 95 | +<tr><td> </td> |
| 96 | +<td align=center class='quality4' width=\"$q4\">".($q4>10?$q4:"")."</td> |
| 97 | +<td align=center class='quality3' width=\"$q3\">".($q3>10?$q3:"")."</td> |
| 98 | +<td align=center class='quality2' width=\"$q2\">".($q2>10?$q2:"")."</td> |
| 99 | +<td align=center class='quality1' width=\"$q1\">".($q1>10?$q1:"")."</td> |
| 100 | +<td align=center class='quality0' width=\"$q0\">".($q0>10?$q0:"")."</td> |
| 101 | +</tr></table>"; |
| 102 | + |
| 103 | + return $title->exists() |
| 104 | + ? "{$dm}{$plink} {$dm}{$size} $table" |
| 105 | + : "<s>{$dm}{$plink} {$dm}{$size}</s>"; |
| 106 | + } |
| 107 | +} |
Index: trunk/extensions/ProofreadPage/ProofreadPage.sql |
— | — | @@ -0,0 +1,15 @@ |
| 2 | +-- Table for the ProofreadPage extension. |
| 3 | +-- Holds a count of the number of pages at each quality level |
| 4 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/pr_index ( |
| 5 | + -- Foreign key to page.page_id |
| 6 | + pr_page_id integer NOT NULL, |
| 7 | + -- number of pages in index |
| 8 | + pr_count integer NOT NULL default '0', |
| 9 | + -- number of pages in each quality level |
| 10 | + pr_q0 integer NOT NULL default '0', |
| 11 | + pr_q1 integer NOT NULL default '0', |
| 12 | + pr_q2 integer NOT NULL default '0', |
| 13 | + pr_q3 integer NOT NULL default '0', |
| 14 | + pr_q4 integer NOT NULL default '0', |
| 15 | + PRIMARY KEY (pr_page_id) |
| 16 | +) ; |