Example #1
0
def process_parcel(parcel):

        global parcel_set, z, node_set, submarket, esubmarket, isr, parcelfees, costdiscount
        global NOZONINGCNT, NOBUILDTYPES
        global building_sqft
        
        ###################
        # CAUTION: unfortunately, there's more scenario-specific stuff
        # that has to wait until the parcel is identified
        if parcel_set['tpp_id'][parcel] == -1: costdiscount = 0.0
        ###################

        debugoutput = ''
 
        current_year = SimulationState().get_current_time()
        pid = parcel_set['parcel_id'][parcel]
        county_id = parcel_set['county_id'][parcel]
        taz = parcel_set['zone_id'][parcel]
        node_id = parcel_set['node_id'][parcel]
        existing_sqft = building_sqft[parcel]

        existing_price = building_price[parcel]
        if existing_sqft < 0: existing_sqft = 0
        if existing_price < 0: existing_price = 0
        if DEBUG: print "parcel_id is %d" % pid
        if DEBUG > 0: print "node_id is %d" % node_id
        shape_area = parcel_set['shape_area'][parcel]
        v = float(shape_area)*10.7639
        #set_value(excel,sp,"Bldg Form","C28",v)

        try: zoning = z.get_zoning(pid)
        except: 
            #print "Can't find zoning for parcel: %d, skipping" % pid
            return
        btypes = z.get_building_types(pid)
        if not zoning:
            #print "NO ZONING FOR PARCEL"
            NOZONINGCNT += 1
            return
        if not btypes:
            #print "NO BUILDING TYPES FOR PARCEL"
            NOBUILDTYPES += 1
            return
        if v < 800:
            #print "PARCEL SIZE IS TOO SMALL"
            return
        if DEBUG > 0: print "Parcel size is %f" % v
        far = z.get_attr(zoning,'max_far', 100)
        height = int(z.get_attr(zoning,'max_height', 1000))
        max_dua = int(z.get_attr(zoning,'max_dua', 100))
        max_dua = min(max_dua,30)
        if DEBUG: print far, height, max_dua

        if far == 100 and height == 1000: far,height = .75,10
            
        bform = BForm(pid,v,far,height,max_dua,county_id,taz,isr,parcelfees,existing_sqft,existing_price)

        if DEBUG > 0: print "ZONING BTYPES:", btypes

        # right now we can't have MF-CONDO (type 5)
        devmdl_btypes = []
        if 1 in btypes: devmdl_btypes+=[1,2]
        if 2 in btypes or 3 in btypes: 
            devmdl_btypes+=[3,5] # MF to MF-rental and MF-condo
        if 4 in btypes: devmdl_btypes.append(7) # office to office
        #if 5 in btypes: continue # hotel
        #if 6 in btypes: continue # schools
        if 7 in btypes or 8 in btypes: # light industrial and warehouse to warehouse
            devmdl_btypes.append(13) 
        if 9 in btypes: devmdl_btypes.append(12) # heavy industrial to manufacturing
        if 10 in btypes: devmdl_btypes.append(10) # strip mall to auto
        if 11 in btypes: devmdl_btypes.append(11) # big box to big box
        if 12 in btypes: devmdl_btypes+=[4,6] # residential-focused to MXD-MF and MXD-condo
        if 13 in btypes: devmdl_btypes.append(9) # retail focused to neighborhood retail
        if 14 in btypes: devmdl_btypes.append(7) # employment-focused to MXD-office

        btypes = devmdl_btypes
        #print btypes

        idx_node_parcel = numpy.where(node_set['node_id']==node_id)[0]

        if DEBUG > 0: print "DEVMDL BTYPES:", btypes

        maxnpv, maxbuilding = 0, -1
        ## number of units and sqft_per_unit by number of bedrooms (1, 2, 3, 4)
        units = zeros(4, dtype='i4')
        sqft_per_unit = zeros(4, dtype='i4')

        for btype in btypes:
            
            if DEBUG > 0: print "building type = %s" % btype
            
            if 1: #btype in [1,2,3,4,5,6]: # RESIDENTIAL
                zone_id = parcel_set['zone_id'][parcel]
                lotsize = node_set['avg_sf_lot_size'][idx_node_parcel][0]
                unitsize = node_set['avg_sf_unit_size'][idx_node_parcel][0]
                unitsize2 = node_set['avg_mf_unit_size'][idx_node_parcel][0]
                unitprice = node_set['avg_sf_unit_price'][idx_node_parcel][0]
                unitprice2 = node_set['avg_mf_unit_price'][idx_node_parcel][0]
                unitrent = node_set['avg_sf_unit_rent'][idx_node_parcel][0]
                unitrent2 = node_set['avg_mf_unit_rent'][idx_node_parcel][0]
                of_rent_sqft = node_set['avg_of_sqft_rent'][idx_node_parcel][0]
                ret_rent_sqft = node_set['avg_ret_sqft_rent'][idx_node_parcel][0]
                ind_rent_sqft = node_set['avg_ind_sqft_rent'][idx_node_parcel][0]
            if not unitsize: unitsize = 1111  
            if unitsize<250:  unitsize = 1111   
            if unitsize>8000:  unitsize = 8000
            if not unitsize2: unitsize2 = 888  
            if unitsize2<250:  unitsize2 = 888   
            if unitsize2>6000:  unitsize2 = 6000
            price_per_sqft_sf = (unitprice*1.0)/unitsize
            price_per_sqft_mf = (unitprice2*1.0)/unitsize2
            rent_per_sqft_sf = (unitrent*1.0)/unitsize
            rent_per_sqft_mf = (unitrent2*1.0)/unitsize2
            if numpy.isinf(price_per_sqft_sf): price_per_sqft_sf = 0
            if numpy.isinf(price_per_sqft_mf): price_per_sqft_mf = 0
            if numpy.isinf(rent_per_sqft_sf): rent_per_sqft_sf = 0
            if numpy.isinf(rent_per_sqft_mf): rent_per_sqft_mf = 0
            if numpy.isinf(of_rent_sqft): of_rent_sqft = 0
            if numpy.isinf(ret_rent_sqft): ret_rent_sqft = 0
            if numpy.isinf(ind_rent_sqft): ind_rent_sqft = 0
            if of_rent_sqft < 7: of_rent_sqft = 7
            if ret_rent_sqft < 7: ret_rent_sqft = 7
            if ind_rent_sqft < 7: ind_rent_sqft = 7
            #if price_per_sqft_mf > 700: price_per_sqft_mf = 700
            #price_per_sqft_mf *= .35
            price_per_sqft_mf *= price_shifters['price_per_sqft_mf']
            #if price_per_sqft_mf > 1.5 * price_per_sqft_sf:
            #    price_per_sqft_mf = 1.5 * price_per_sqft_sf
            #price_per_sqft_mf = price_per_sqft_sf*.5
            if DEBUG > 0: print "price_per_sqft_sf:", price_per_sqft_sf, "price_per_sqft_mf:", price_per_sqft_mf, "rent_per_sqft_sf:", rent_per_sqft_sf, "rent_per_sqft_mf:", rent_per_sqft_mf
            if DEBUG > 0: print "of_rent_sqft:", of_rent_sqft, "ret_rent_sqft:", ret_rent_sqft, "ind_rent_sqft:", ind_rent_sqft
            #prices = (price_per_sqft_sf*1.2,price_per_sqft_mf,rent_per_sqft_sf,rent_per_sqft_mf*2,of_rent_sqft*1.85,ret_rent_sqft*1.85,ind_rent_sqft*2.5)
            prices = (price_per_sqft_sf*1.0*price_shifters['price_per_sqft_sf'],
                      price_per_sqft_mf*1.0,
                      rent_per_sqft_sf*1.0*price_shifters['rent_per_sqft_sf'],
                      rent_per_sqft_mf*1.0*price_shifters['rent_per_sqft_mf'],
                      of_rent_sqft*price_shifters['of_rent_sqft'],
                      ret_rent_sqft*price_shifters['ret_rent_sqft'],
                      ind_rent_sqft*price_shifters['ind_rent_sqft'])
            if not lotsize: lotsize = 11111    
            if lotsize <1000:  lotsize = 11111   
            if lotsize>20000: lotsize=20000
            if DEBUG > 0: print "zone:", zone_id, "lotsize:", lotsize, "HS size:", unitsize, "MF size:", unitsize2
            bform.set_unit_sizes(lotsize,unitsize,unitsize2)

            bform.set_btype(btype)

            parking = z.get_parking_requirements(pid, btype)

            bform.set_parking(parking)

            #if 1: print btype
            pjurisdiction = parcel_set['jurisdiction_id'][parcel]
            pschooldistrict = parcel_set['schooldistrict'][parcel]
            ptransit = parcel_set['within_half_mile_transit'][parcel]
            from numpy import logical_and, where
            sub_idx = where(logical_and(submarket['schooldistrict'] == pschooldistrict,
                                       submarket['within_half_mile_transit'] == ptransit)
                           )[0]
            submarket_info = {}
            for attr in submarket.get_known_attribute_names():
                submarket_info[attr] = submarket[attr][sub_idx]
            esub_idx = where(logical_and(esubmarket['jurisdiction_id'] == pjurisdiction,
                                        esubmarket['within_half_mile_transit'] == ptransit)
                           )[0]
            esubmarket_info = {}
            for attr in esubmarket.get_known_attribute_names():
                esubmarket_info[attr] = esubmarket[attr][esub_idx]
            
            submarket_pool = submarkets.setup_dataset_pool(opus=False,btype=btype,submarket_info=submarket_info,esubmarket_info=esubmarket_info)

            X, npv = devmdl_optimize.optimize(bform,prices,costdiscount,
                                              submarket_pool)
            if DEBUG: print X, npv

            bformdbg = (county_id,far,height,max_dua,bform.sf_builtarea(),bform.sfunitsizes,bform.mf_builtarea(),bform.mfunitsizes,bform.num_units,bform.nonres_sqft,bform.buildable_area)
            pfeesstr = ''
            if parcelfees: pfeesstr = parcelfees.get(pid)

            otherdbg = (isr,pfeesstr,existing_sqft,existing_price,lotsize,unitsize,unitsize2,string.join([str(x) for x in bform.sales_absorption],'|'),string.join([str(x) for x in bform.rent_absorption],'|'),string.join([str(x) for x in bform.leases_absorption],'|'),string.join([str(x) for x in bform.sales_vacancy_rates],'|'),string.join([str(x) for x in bform.vacancy_rates],'|'))
            debugoutput += string.join([str(x) for x in [pid,btype,npv,bform.actualfees]+list(prices)+list(bformdbg)+list(otherdbg)]
,sep=',')+'\n'
            #if npv == -1: return # error code
            if npv > maxnpv:
                maxnpv = npv
                nonres_sqft = bform.nonres_sqft
                sqft = nonres_sqft # add residential below
                if btype in [1,2,3,4,5,6]: # RESIDENTIAL
                    if btype in [1,2]: 
                        res_sqft = bform.sf_builtarea()
                        sqft_per_unit = bform.sfunitsizes
                    else: 
                        res_sqft = bform.mf_builtarea()
                        sqft_per_unit = bform.mfunitsizes
                    sqft += res_sqft
                    res_units = sum(bform.num_units)
                else:
                    res_sqft = 0
                    res_units = 0
                stories = sqft / bform.buildable_area

                #this is to be recoded tenure: 1 - rent, 2 - own from 0 - own, 1 - rent
                tenure = 0
                if btype in [3,4]: tenure = 1
                year_built = current_year
                stories = math.ceil(stories)
                sqft = math.floor(sqft)
                res_sqft = math.floor(res_sqft)
                nonres_sqft = math.floor(nonres_sqft)
                res_units = math.ceil(res_units) # these are partial units, but usually very close to one
                # it's not mixed if the nonres gets optimized out
                if btype == 12 and nonres_sqft == 0: btype = 3 
                building = (pid, county_id, btype, stories, sqft, res_sqft, nonres_sqft, tenure, year_built, res_units, npv, bform.actualfees)
                maxbuilding = building
                units = bform.num_units

        return maxbuilding, (units, sqft_per_unit), debugoutput
Example #2
0
  try:
    pid = int(r['pid'])
  except:
    continue # some bad logging info
  parcel_size = float(r['bform.buildable_area'])/.8
  far = float(r['far'])
  height = float(r['height'])
  max_dua = float(r['max_dua'])
  county_id = int(r['county_id'])
  taz = -1 # as long as isr below is off this won't be used 
  isr = None
  parcelfees = None
  existing_sqft = float(r['existing_sqft'])
  existing_price =  float(r['existing_price'])

  bform = BForm(pid,parcel_size,far,height,max_dua,county_id,taz,isr,parcelfees,existing_sqft,existing_price)
  lotsize = float(r['lotsize'])
  unitsize = float(r['unitsize'])
  unitsize2 = float(r['unitsize2'])
  bform.set_unit_sizes(lotsize,unitsize,unitsize2)
  btype = int(r['btype'])
  bform.set_btype(btype)
  
  prices = (r['pricesf'],r['pricemf'],r['rentsf'],r['rentmf'],r['rentof'],r['rentret'],r['rentind'])
  prices = tuple([float(x) for x in prices])
  prices
  costdiscount = 0.0

  submarket_pool = submarkets.setup_dataset_pool(opus=False,btype=btype, \
                                   submarket_info=None,esubmarket_info=None)
Example #3
0
def process_parcel(parcel):

        global parcel_set, z, node_set, zone_set, submarket, esubmarket, isr, parcelfees, costdiscount, i
        global NOZONINGCNT, NOBUILDTYPES
        global building_sqft

        debugoutput = ''
        current_year = SimulationState().get_current_time()
        pid = parcel_set['parcel_id'][parcel]
        county_id = parcel_set['county_id'][parcel]
        taz = parcel_set['zone_id'][parcel]
        if NODES:
            node_id = parcel_set['node_id'][parcel]
        
        zoning_id = parcel_set['zoning_id'][parcel]
        
        existing_sqft = building_sqft[parcel]

        existing_price = building_price[parcel]
        if existing_sqft < 0: existing_sqft = 0
        if existing_price < 0: existing_price = 0
        if DEBUG: print "parcel_id is %d" % pid
        shape_area = parcel_set['parcel_sqft'][parcel]
        v = float(shape_area) #*10.7639
        
        if URBANVISION:
            #try: zoning = z.get_zoning(pid)
            try: zoning = zoning_id
            except: 
                return
            if zoning < 1:
                return
            btypes = z.get_building_types(zoning)

            if not zoning:
                NOZONINGCNT += 1
                return
            if not btypes:
                NOBUILDTYPES += 1
                return
            if v < 800:
                return
            if DEBUG > 0: print "Parcel size is %f" % v
            ####################### Not having max far , max height, max dua
            far = z.get_far(pid)
            # height = int(z.get_attr(zoning,'max_height', 1000))
            # max_dua = int(z.get_attr(zoning,'max_dua', 100))
            # max_dua = min(max_dua,50)
            
            #far = 2
            height = 400
            max_dua = 100
            if DEBUG: print far, height, max_dua
            if far == 100 and height == 1000: far,height = .75,10
            bform = BForm(pid,v,far,height,max_dua,county_id,taz,isr,parcelfees,existing_sqft,existing_price)
        else:
            print "Need to flesh out the case where zoning data is entirely in cache"
            #bform = BForm(pid,v,far,height,max_dua,county_id,taz,isr,parcelfees,existing_sqft,existing_price)

        
        ################################################!!!!!!!!! Need to clarify the developer model's building typology
        if DEBUG > 0: print "ZONING BTYPES:", btypes

        devmdl_btypes = []
        if 20 in btypes: devmdl_btypes+=[1,2] ##sf detached
        if 24 in btypes or 3 in btypes or 2 in btypes: ##sf attached and multifamily
            devmdl_btypes+=[3,5] # MF to MF-rental and MF-condo
        if 5 in btypes: devmdl_btypes.append(7) # office to office
        if 22 in btypes: # warehouse to warehouse
            devmdl_btypes.append(13)
        if 9 in btypes: devmdl_btypes.append(12) #industrial to manufacturing
        if 18 in btypes: devmdl_btypes+=[10,11,9] #retail to retail
        if 11 in btypes: devmdl_btypes+=[4,6] # mixed to MXD-MF and MXD-condo

        btypes = devmdl_btypes
        #print btypes
        if NODES:
            idx_node_parcel = numpy.where(node_set['node_id']==node_id)[0]
        else:
            idx_zone_parcel = numpy.where(zone_set['zone_id']==taz)[0]

        if DEBUG > 0: print "DEVMDL BTYPES:", btypes
        
        npv = 0
        maxnpv, maxbuilding = 0, -1
        ## number of units and sqft_per_unit by number of bedrooms (1, 2, 3, 4)
        units = zeros(4, dtype='i4')
        sqft_per_unit = zeros(4, dtype='i4')

        for btype in btypes:
            
            if DEBUG > 0: print "building type = %s" % btype
            
            if 1: #btype in [1,2,3,4,5,6]: # RESIDENTIAL
                if NODES:
                    zone_id = parcel_set['zone_id'][parcel]
                    lotsize = node_set['avg_sf_lot_size'][idx_node_parcel][0]
                    unitsize = node_set['avg_sf_unit_size'][idx_node_parcel][0]
                    unitsize2 = node_set['avg_mf_unit_size'][idx_node_parcel][0]
                    unitprice = node_set['avg_sf_unit_price'][idx_node_parcel][0]
                    unitprice2 = node_set['avg_mf_unit_price'][idx_node_parcel][0]
                    unitrent = node_set['avg_sf_unit_rent'][idx_node_parcel][0]
                    unitrent2 = node_set['avg_mf_unit_rent'][idx_node_parcel][0]
                    of_rent_sqft = node_set['avg_of_sqft_rent'][idx_node_parcel][0]
                    ret_rent_sqft = node_set['avg_ret_sqft_rent'][idx_node_parcel][0]
                    ind_rent_sqft = node_set['avg_ind_sqft_rent'][idx_node_parcel][0]
                else:
                    print "Need to flesh this section out with zonal variables"
            if not unitsize: unitsize = 1111  
            if unitsize<250:  unitsize = 1111   
            if unitsize>8000:  unitsize = 8000
            if not unitsize2: unitsize2 = 888  
            if unitsize2<250:  unitsize2 = 888   
            if unitsize2>6000:  unitsize2 = 6000
            price_per_sqft_sf = (unitprice*1.0)/unitsize
            price_per_sqft_mf = (unitprice2*1.0)/unitsize2
            rent_per_sqft_sf = (unitrent*1.0)/unitsize
            rent_per_sqft_mf = (unitrent2*1.0)/unitsize2
            if numpy.isinf(price_per_sqft_sf): price_per_sqft_sf = 0
            if numpy.isinf(price_per_sqft_mf): price_per_sqft_mf = 0
            if numpy.isinf(rent_per_sqft_sf): rent_per_sqft_sf = 0
            if numpy.isinf(rent_per_sqft_mf): rent_per_sqft_mf = 0
            if numpy.isinf(of_rent_sqft): of_rent_sqft = 0
            if numpy.isinf(ret_rent_sqft): ret_rent_sqft = 0
            if numpy.isinf(ind_rent_sqft): ind_rent_sqft = 0
            if of_rent_sqft < 7: of_rent_sqft = 7
            if ret_rent_sqft < 7: ret_rent_sqft = 7
            if ind_rent_sqft < 7: ind_rent_sqft = 7
            #if price_per_sqft_mf > 700: price_per_sqft_mf = 700
            #price_per_sqft_mf *= .35
            price_per_sqft_mf *= price_shifters['price_per_sqft_mf']
            #if price_per_sqft_mf > 1.5 * price_per_sqft_sf:
            #    price_per_sqft_mf = 1.5 * price_per_sqft_sf
            #price_per_sqft_mf = price_per_sqft_sf*.5
            if DEBUG > 0: print "price_per_sqft_sf:", price_per_sqft_sf, "price_per_sqft_mf:", price_per_sqft_mf, "rent_per_sqft_sf:", rent_per_sqft_sf, "rent_per_sqft_mf:", rent_per_sqft_mf
            if DEBUG > 0: print "of_rent_sqft:", of_rent_sqft, "ret_rent_sqft:", ret_rent_sqft, "ind_rent_sqft:", ind_rent_sqft
            #prices = (price_per_sqft_sf*1.2,price_per_sqft_mf,rent_per_sqft_sf,rent_per_sqft_mf*2,of_rent_sqft*1.85,ret_rent_sqft*1.85,ind_rent_sqft*2.5)
            prices = (price_per_sqft_sf*1.0*price_shifters['price_per_sqft_sf'],
                      price_per_sqft_mf*1.0,
                      rent_per_sqft_sf*1.0*price_shifters['rent_per_sqft_sf'],
                      rent_per_sqft_mf*1.0*price_shifters['rent_per_sqft_mf'],
                      of_rent_sqft*price_shifters['of_rent_sqft'],
                      ret_rent_sqft*price_shifters['ret_rent_sqft'],
                      ind_rent_sqft*price_shifters['ind_rent_sqft'])
            if not lotsize: lotsize = 11111    
            if lotsize <1000:  lotsize = 11111   
            if lotsize>20000: lotsize=20000
            if DEBUG > 0: print "zone:", zone_id, "lotsize:", lotsize, "HS size:", unitsize, "MF size:", unitsize2
            bform.set_unit_sizes(lotsize,unitsize,unitsize2)

            bform.set_btype(btype)

            #parking = z.get_parking_requirements(pid, btype)
            parking = None

            bform.set_parking(parking)  ############add parking info for DRCOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            #if 1: print btype
            #pjurisdiction = parcel_set['jurisdiction_id'][parcel]
            #pschooldistrict = parcel_set['schooldistrict'][parcel]
            pzone = parcel_set['zone_id'][parcel]
            ptransit = parcel_set['within_half_mile_transit'][parcel]

            sub_idx = where(logical_and(submarket['zone_id'] == taz,
                                       submarket['within_half_mile_transit'] == ptransit)
                           )[0]
            submarket_info = {}
            for attr in submarket.get_known_attribute_names():
                submarket_info[attr] = submarket[attr][sub_idx]
            esub_idx = where(logical_and(esubmarket['zone_id'] == taz,
                                        esubmarket['within_half_mile_transit'] == ptransit)
                           )[0]
            esubmarket_info = {}
            for attr in esubmarket.get_known_attribute_names():
                esubmarket_info[attr] = esubmarket[attr][esub_idx]
            
            submarket_pool = submarkets.setup_dataset_pool(opus=False,btype=btype,submarket_info=submarket_info,esubmarket_info=esubmarket_info)  ###Look into this
            
            X, npv = devmdl_optimize.optimize(bform,prices,costdiscount,
                                              submarket_pool)
            if DEBUG: print X, npv
            bformdbg = (county_id,far,height,max_dua,bform.sf_builtarea(),bform.sfunitsizes,bform.mf_builtarea(),bform.mfunitsizes,bform.num_units,bform.nonres_sqft,bform.buildable_area)
            pfeesstr = ''
            if parcelfees: pfeesstr = parcelfees.get(pid)

            otherdbg = (isr,pfeesstr,existing_sqft,existing_price,lotsize,unitsize,unitsize2,string.join([str(x) for x in bform.sales_absorption],'|'),string.join([str(x) for x in bform.rent_absorption],'|'),string.join([str(x) for x in bform.leases_absorption],'|'),string.join([str(x) for x in bform.sales_vacancy_rates],'|'),string.join([str(x) for x in bform.vacancy_rates],'|'))
            debugoutput += string.join([str(x) for x in [pid,btype,npv,bform.actualfees]+list(prices)+list(bformdbg)+list(otherdbg)]
,sep=',')+'\n'
            #if npv == -1: return # error code
            if npv > maxnpv:
                maxnpv = npv
                nonres_sqft = bform.nonres_sqft
                sqft = nonres_sqft # add residential below
                if btype in [1,2,3,4,5,6]: # RESIDENTIAL 
                    if btype in [1,2]: 
                        res_sqft = bform.sf_builtarea()
                        sqft_per_unit = bform.sfunitsizes
                    else: 
                        res_sqft = bform.mf_builtarea()
                        sqft_per_unit = bform.mfunitsizes
                    sqft += res_sqft
                    res_units = sum(bform.num_units)
                else:
                    res_sqft = 0
                    res_units = 0
                stories = sqft / bform.buildable_area

                #this is to be recoded tenure: 1 - rent, 2 - own from 0 - own, 1 - rent
                tenure = 0
                if btype in [3,4]: tenure = 2
                year_built = current_year
                stories = math.ceil(stories)
                sqft = math.floor(sqft)
                res_sqft = math.floor(res_sqft)
                nonres_sqft = math.floor(nonres_sqft)
                res_units = math.ceil(res_units) # these are partial units, but usually very close to one
                # it's not mixed if the nonres gets optimized out
                #if btype in [4,6] and nonres_sqft == 0: btype = 3
                if btype in [1,2]: btype = 20
                if btype in [3,4]: btype = 2
                if btype in [5,6]: btype = 3
                if btype in [7,8]: btype = 5
                if btype in [9,10,11]: btype = 18
                if btype == 12: btype = 9
                if btype == 13: btype = 22
                if btype == 14: btype = 23
                building = (pid, county_id, btype, stories, sqft, res_sqft, nonres_sqft, tenure, year_built, res_units, npv, bform.actualfees)
                maxbuilding = building
                units = bform.num_units
                
        return maxbuilding, (units, sqft_per_unit), debugoutput