
# keyed by code
# 'name' should always be there
# keep up to 'keep' (defaults to 1 below after decl)
# if 'doub' treat as a double, that many per volume (GN has 6 per)
# if 'seek' keep seeking a real copy of the book to own
# if 'box' is there and true it describes the boxed/boxing behavior:
#    sfwa[p] vs reserve; dsfwa vs dreserve (doubles); solo vs selves; all


%category =
  (
   'A' => {
	   'name' => 'Art Book',
	   'seek' => 1,
	  },
   'B' => {
	   'name' => 'Booklet',
	   'seek' => 1,
	  },
   'BD' => {
            'name' => 'Booklet Double',
            'doub' => 2,
           },
   'BLB' => {
	     'name' => 'Big (or Better) Little Book',
	     'seek' => 1,
	    },
   'BS' => {
	    'name' => 'Binary Star',
	    'doub' => 2,
	    'seek' => 1,
	   },
   'C/BS' => {
	      'name' => 'Circulating Binary Star',
	      'keep' => 2,                                    # why?
	      'doub' => 2,
	      'seek' => 1,
	      'box' => 'all',
	     },
   'C/D' => {
	     'name' => 'Circulating Ace Double',
	     'keep' => 3,
	     'doub' => 2,
	     'seek' => 1,
	     'box' => 'all',
	    },
   'C/ERD' => {
	     'name' => 'Circulating Eraserhead Double',
	     'keep' => 2,
	     'doub' => 2,
	     'seek' => 1,
	     'box' => 'all',
	    },
   'C/GRD' => {
	       'name' => 'Circulating Gryphon Double',
	       'keep' => 2,
	       'doub' => 2,
	       'seek' => 1,
	       'box' => 'all',
	     },
   'C/GZD' => {
	       'name' => 'Circulating Gollancz Double',
	       'keep' => 2,
	       'doub' => 2,
	       'seek' => 1,
	       'box' => 'all',
	      },
   'C/MB' => {
	      'name' => 'Circulating Millenium Binary',
	      'keep' => 2,                                    # why?
	      'doub' => 2,
	      'seek' => 1,
	      'box' => 'all',
	     },
   'C/MM' => {
       'name' => 'Circulating Mixed Midia',
       'keep' => 100,
   },
   'C/OVD' => {
	       'name' => 'Circulating Ocean View Double',
	       'keep' => 2,
	       'doub' => 2,
	       'seek' => 1,
	       'box' => 'all',
	      },
   'C/P' => {
	     'name' => 'Circulating Paperback',
	     'keep' => 1e6,
	     'soft' => 2,  # soft limit enforced by occasional sweeps
	    },
   'C/PA' => {
	      'name' => 'Circulating Paperback Anthology',
	      'keep' => 2,
	     },
   'C/RAN-H' => {
		 'name' => 'Random Hardcover',
		 'keep' => 3,
		 'box' => 'all',
		},
   'C/RAN-P' => {
		 'name' => 'Random Paperback',
		 'keep' => 2,
		 'box' => 'all',
		},
   'C/REF-H' => {
		 'name' => 'Reference Hardcover',
		 'keep' => 3,
		 'box' => 'solo',
		},
   'C/REF-P' => {
		 'name' => 'Reference Paperback',
		 'keep' => 2,
		 'box' => 'solo',
		},
   'C/TD' => {
	      'name' => 'Circulating Tor Double',
	      'keep' => 2,
	      'doub' => 2,
	      'seek' => 1,
	      'box' => 'all',
	     },
   'CAL' => {
	     'name' => 'Calendar',
	     'seek' => 1,
	    },
   'CX' => {
	    'name' => 'Comics',
	   },
   'D' => {
	   'name' => 'Ace Double',
	   'doub' => 2,
	   'seek' => 1,
	  },
   'DICT' => {
	      'name' => 'Dictionary',
	     },
   'ERD' => {
	     'name' => 'Eraserhead Double',
	     'doub' => 2,
	     'seek' => 1,
	    },
   'FH' => {
	    'name' => 'Foreign-language Hardcover',
	    'seek' => 1,
	   },
   'FP' => {
	    'name' => 'Foreign-language Paperback',
	    'seek' => 1,
	   },
   'FPR' => {
	     'name' => 'Foreign-language Perry Rodan',
	     'seek' => 1,
	    },
   'GN' => {
	    'name' => 'Galaxy Novel',
	    'doub' => 100, # never group implicitly, only explicitly, they suck
	    'seek' => 1,
	   },
   'GRD' => {
	     'name' => 'Gryphon Double',
	     'doub' => 2,
	     'seek' => 1,
	   },
   'GZD' => {
	     'name' => 'Gollancz Double',
	     'doub' => 2,
	     'seek' => 1,
	    },
   'H' => {
	   'name' => 'Hardcover',
	   'keep' => 3,
	  },
   'HA' => {
	    'name' => 'Hardcover Anthology',
	    'keep' => 3,
	   },
   'LP' => {
	    'name' => 'Large Paperback',
	    'box' => 'reserve',
	   },
   'LPA' => {
	     'name' => 'Large Paperback Anthology',
	     'box' => 'reserve',
	    },
   'MB' => {
	    'name' => 'Millenium Binary',
	    'doub' => 2,
	    'seek' => 1,
	   },
   'OVD' => {
	     'name' => 'Ocean View Double',
	     'doub' => 2,
	     'seek' => 1,
	    },
   'P' => {
	   'name' => 'Paperback',
	   'box' => 'reserve',
	  },
   'PA' => {
	    'name' => 'Paperback Anthology',
	    'box' => 'reserve',
	   },
   'R/IND' => {
	       'name' => 'Index',
	       'keep' => 100,
	      },
   'R/IND-F' => {
		 'name' => 'Index Folder',
		},
   'R/REF-H' => {
		 'name' => 'Reference Hardcover',
		 'box' => 'reserve',
		},
   'R/REF-P' => {
		 'name' => 'Reference Paperback',
		 'box' => 'reserve',
		},
   'SCX' => {
	     'name' => 'Small Comics',
	    },
   'SFWA' => {
	      'name' => 'SFWA Hardcover',
	      'keep' => 100,
	      'seek' => 1,
	      'box' => 'sfwa',
	     },
   'SFWA-P' => {
		'name' => 'SFWA Paperback',
		'keep' => 100,
		'seek' => 1,
		'box' => 'sfwap',
	       },
   'SFWA-TD' => {
		 'name' => 'SFWA Tor Double',
		 'keep' => 100,
		 'doub' => 2,
		 'seek' => 1,
		 'box' => 'dsfwa',
		},
   'SFWA-VLP' => {
		  'name' => 'SFWA Very Large Paperback',
		  'keep' => 100,
		  'seek' => 1,
		 },
   'SR-D' => {
	      'name' => 'Special Reserve Ace Double',
	      'doub' => 2,
	      'seek' => 1,
	     },
   'SR-DNESFA' => {
		   'name' => 'Special Reserve NESFA Double',
		   'keep' => 3,
		   'doub' => 2,
		  },
   'SR-H' => {
	      'name' => 'Special Reserve Hardcover',
	      'keep' => 100,
	     },
   'SR-HA' => {
	       'name' => 'Special Reserve Hardcover Anthology',
	      },
   'SR-L' => {
	      'name' => 'Special Reserve Locked Cabinet',
	     },
   'SR-LP' => {
	       'name' => 'Special Reserve Large Paperback',
	       'keep' => 100,
	      },
   'SR-LPA' => {
		'name' => 'Special Reserve Large Paperback Anthology',
		'keep' => 100,
	       },
   'SR-MM' => {
	       'name' => 'Special Reserve Mixed Media',
	       'seek' => 1,
	       'keep' => 3,
	      },
   'SR-P' => {
	      'name' => 'Special Reserve Paperback',
	      'keep' => 100,
	     },
   'SR-PA' => {
	       'name' => 'Special Reserve Paperback Anthology',
	      },
   'SR-S' => {
	      'name' => 'Special Reserve Script',
	      'keep' => 3,
	      'seek' => 1,
	     },
   'SR-VLH' => {
		'name' => 'Special Reserve Very Large Hardcover',
	       },
   'SR-VLHA' => {
		 'name' => 'Special Reserve Very Large Hardcover Anthology',
	       },
   'SR-VLP' => {
		'name' => 'Special Reserve Very Large Paperback',
	       },
   'SR-VLPA' => {
		 'name' => 'Special Reserve Very Large Paperback Anthology',
		},
   'SRL/IND' => {
		 'name' => 'Locked Index',
		},
   'TD' => {
	    'name' => 'Tor Double',
	    'doub' => 2,
	    'seek' => 1,
	    'box' => 'dreserve',
	   },
   'VLH' => {
	   'name' => 'Very Large Hardcover',
	   'keep' => 100,
	  },
   'VLP' => {
	     'name' => 'Very Large Paperback',
	    },
   'VLPA' => {
	      'name' => 'Very Large Paperback Anthology',
	     },
   'WRD' => {
	     'name' => 'Weird Categories',
	     'keep' => 100,
	     'seek' => 1,
	    },
   'DM/H' => {
       'name' => 'DexMistress (temporary) Hardcover'
   },
   'KBX/H' => {
       'name' => 'Keep BoXed / Hardcover',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'KBX/HA' => {
       'name' => 'Keep BoXed / Hardcover Anthology',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'KBX/P' => {
       'name' => 'Keep BoXed / Paperback',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'KBX/PA' => {
       'name' => 'Keep BoXed / Paperback Anthology',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'KBX/REF-P' => {
       'name' => 'Keep BoXed / Reference Paperback',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'KBX/REF-H' => {
       'name' => 'Keep BoXed / Reference Hardcover',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/H' => {
       'name' => 'Hasslecomm (temporary) / Hardcover',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/HA' => {
       'name' => 'Hasslecomm (temporary) / Hardcover Anthology',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/P' => {
       'name' => 'Hasslecomm (temporary) / Paperback',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/PA' => {
       'name' => 'Hasslecomm (temporary) / Paperback Anthology',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/REF-P' => {
       'name' => 'Hasslecomm (temporary) / Reference Paperback',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
   'HASSLE/REF-H' => {
       'name' => 'Hasslecomm (temporary) / Reference Hardcover',
       'keep' => 1e6,
       'doub' => -1, # Not actually a double, but we're taunting dexmaster here
   },
  );

foreach (keys %category) {
  die "category $_ unnamed" unless exists $category{$_}{'name'};

  # a double's shelfcode's base may not have 'D' as the 2nd-to-last letter
  # (so that it can be parsed into basecode & letter? & number properly)  
  die "bad double code $_" if $category{$_}{'doub'} and /D.$/;

  # base shelfcodes can't have numbers in them (doubles' extensions can)
  die "bad code $_" if /\d/;

  $category{$_}{'keep'} ||= 1;
  $category{$_}{'soft'} ||= $category{$_}{'keep'};
}


1;
