Pre-github

This commit is contained in:
Jason
2026-04-24 14:09:04 -05:00
parent 7a2fffd62e
commit fcaa15bf6e
68 changed files with 707 additions and 10574 deletions
-7
View File
@@ -1,7 +0,0 @@
# Apache configuration for Flask subdirectory deployment
# Passenger configuration ONLY - minimal to avoid blocking issues
PassengerEnabled on
PassengerAppRoot /home/bmdwtjuw/product-finder
PassengerPython /home/bmdwtjuw/virtualenv/product-finder/3.13/bin/python3.13_bin
SetEnv APPLICATION_ROOT /product-finder
-4
View File
@@ -1,4 +0,0 @@
# MINIMAL .htaccess for troubleshooting
# If you're getting 403/404, try this simplified version first
PassengerEnabled on
+147
View File
@@ -0,0 +1,147 @@
# Product App - Modular Flask Application
## 🏗️ Structure
```
product_app/
├── app.py # Main application file
├── passenger_wsgi.py # Passenger WSGI entry point for production
├── requirements.txt # Python dependencies
├── blueprints/ # Modular routes organized by feature
│ ├── __init__.py
│ ├── auth.py # Login/logout/session management
│ └── users.py # User CRUD operations
├── templates/ # HTML templates
│ ├── login.html
│ └── user_manager.html
└── data/ # Data storage
└── users.json # User accounts with hashed passwords
```
## 🎯 Features Implemented
### ✅ Authentication System (blueprints/auth.py)
- Login with username/password
- Session management
- Password hashing (PBKDF2-SHA256, 1M iterations)
- Login required decorator
- Permission checking: `can_user('manage_users')`
- User status checking (active/inactive)
### ✅ User Management (blueprints/users.py)
- View all users
- Add new users
- Delete users
- Toggle active/inactive status
- Change passwords (requires admin verification)
- Location-based access control
- Permission system (manage_users, create_quotes, etc.)
- Download users as JSON
## 🔐 Default Login
- **Username:** `Master`
- **Password:** `Master`
- **Permissions:** Full access (manage_users)
## 🚀 Local Testing
```bash
cd product_app
python app.py
```
Visit: http://localhost:8080/
## Routes
### Main Routes
- `/` - Home (redirects to login if not authenticated)
- `/test` - Test page to verify app is running
### Authentication Routes (auth_bp)
- `/login` - Login page
- `/logout` - Logout
- `/api/login` - POST: Login API
- `/api/session` - GET: Current session info
### User Management Routes (users_bp)
- `/users/` - User management page
- `/users/api` - GET: List all users, POST: Add user
- `/users/api/<index>` - DELETE: Delete user
- `/users/api/<index>/active` - PATCH: Toggle active status
- `/users/api/<index>/change-password` - POST: Change password
- `/users/api/download` - GET: Download users.json
## 📦 Production Deployment
### Upload to Server: `/home/bmdwtjuw/product-finder/`
Files to upload:
- `app.py`
- `passenger_wsgi.py` (or just use existing)
- `blueprints/` (entire folder)
- `__init__.py`
- `auth.py`
- `users.py`
- `templates/` (entire folder)
- `login.html`
- `user_manager.html`
- `data/users.json`
### Control Panel Settings
- **Application startup file:** `passenger_wsgi.py` (or `app.py`)
- **Application Entry point:** `application`
- **Python version:** 3.13.11
### Test After Deployment:
1. https://columbiawindows.com/product-finder/test
2. https://columbiawindows.com/product-finder/login
3. Login with Master/Master
4. Test user management
## 🔧 Adding New Features
### Create a New Blueprint
1. Create `blueprints/your_feature.py`:
```python
from flask import Blueprint, render_template
from blueprints.auth import login_required, can_user
your_feature_bp = Blueprint('your_feature', __name__, url_prefix='/your-feature')
@your_feature_bp.route('/')
@login_required
def index():
return render_template('your_feature.html')
```
2. Register in `app.py`:
```python
from blueprints.your_feature import your_feature_bp
app.register_blueprint(your_feature_bp)
```
3. Create `templates/your_feature.html`
4. Test locally, then upload to server
## 📝 Benefits of Blueprint Structure
**Separation of Concerns:** Each feature in its own file
**Easy to Maintain:** Find and edit specific features quickly
**Scalable:** Add new features without touching existing code
**Testable:** Each blueprint can be tested independently
**Reusable:** Share decorators (login_required, permission_required) across blueprints
## 🛠️ Next Steps
- Add more blueprints for other features (quotes, products, etc.)
- Add more templates as needed
- Extend permission system
- Add location selection page
- Add the main product finder quiz
-98
View File
@@ -1,98 +0,0 @@
# Admin Utilities
This folder contains administrative tools and utilities for maintaining the CGW Product Finder application.
## 🛠️ Available Tools
### fix_default_locations.py
**Purpose**: Ensures all users have their default location marked as accessible.
**Usage**:
```bash
cd app/admin
python fix_default_locations.py
```
**What it does**:
- Scans all users in `data/users.json`
- Checks if each user's default location is marked as accessible
- Automatically fixes any users where the default location is not accessible
- Reports results for each user
**When to use**:
- After manual edits to users.json
- After importing users from backup
- If users report they can't access their default location
- As a maintenance check
### test_password_security.py
**Purpose**: Demonstrates and tests the password hashing security implementation.
**Usage**:
```bash
cd app/admin
python test_password_security.py
```
**What it does**:
- Demonstrates PBKDF2-SHA256 password hashing
- Shows security features (iterations, salt, etc.)
- Verifies password verification works correctly
- Useful for understanding the security implementation
**When to use**:
- To verify password hashing is working correctly
- To demonstrate security to stakeholders
- For educational purposes
- When troubleshooting password-related issues
## 📋 Running Admin Tools
All admin tools should be run from within the `app/admin` directory to ensure correct file paths.
**Example**:
```bash
# Navigate to admin folder
cd "C:\Users\Work\Desktop\CGW Product Finder\app\admin"
# Run a tool
python fix_default_locations.py
```
## ⚠️ Important Notes
- **Backup First**: Always backup `data/users.json` before running utilities that modify data
- **Test Environment**: Test utilities in a development environment before running in production
- **File Paths**: These tools assume they're being run from the `app/admin` directory
- **Python Version**: Requires Python 3.7 or higher
## 🔒 Security Considerations
- These tools have direct access to user data
- Do not expose these tools to web-facing directories
- Keep this folder secure with appropriate file permissions
- Never commit sensitive user data to version control
## 📝 Adding New Admin Tools
When adding new administrative tools to this folder:
1. Add the Python script file
2. Update this README with documentation
3. Include clear usage instructions
4. Document any data modifications it makes
5. Include error handling and user feedback
## 🐛 Troubleshooting
**"File not found" errors**:
- Ensure you're running from the `app/admin` directory
- Check that `../data/users.json` exists
**Permission denied**:
- Ensure the application is not running
- Check file permissions on `data/users.json`
**Import errors**:
- Ensure all required dependencies are installed: `pip install -r ../requirements.txt`
- Verify Python version: `python --version`
-65
View File
@@ -1,65 +0,0 @@
"""
Utility script to fix existing users by ensuring their default location
is marked as accessible in their locationSettings.
"""
import json
import os
# Get the directory where this script is located
basedir = os.path.abspath(os.path.dirname(__file__))
USERS_FILE = os.path.join(basedir, '..', 'data', 'users.json')
def fix_default_locations():
"""
Ensure all users have their default location marked as accessible.
"""
if not os.path.exists(USERS_FILE):
print("No users.json file found.")
return
# Load users
with open(USERS_FILE, 'r') as f:
users = json.load(f)
print(f"Found {len(users)} users to check...")
changes_made = 0
for user in users:
username = user.get('username', 'Unknown')
default_location = user.get('defaultLocation')
if not default_location:
print(f"⚠️ User '{username}' has no default location - skipping")
continue
location_settings = user.get('locationSettings', {})
# Check if default location is in settings and accessible
if default_location not in location_settings:
print(f"✓ Adding default location '{default_location}' for user '{username}'")
location_settings[default_location] = {'accessible': True}
user['locationSettings'] = location_settings
changes_made += 1
elif not location_settings[default_location].get('accessible', False):
print(f"✓ Marking default location '{default_location}' as accessible for user '{username}'")
location_settings[default_location]['accessible'] = True
changes_made += 1
else:
print(f" User '{username}' - default location already accessible")
if changes_made > 0:
# Save updated users
with open(USERS_FILE, 'w') as f:
json.dump(users, f, indent=2)
print(f"\n✓ Fixed {changes_made} user(s) and saved to users.json")
else:
print("\n✓ All users already have correct default location settings")
if __name__ == '__main__':
print("=" * 60)
print("DEFAULT LOCATION FIX UTILITY")
print("=" * 60)
print()
fix_default_locations()
print()
-60
View File
@@ -1,60 +0,0 @@
"""
Test script to demonstrate password hashing and verification
"""
from werkzeug.security import generate_password_hash, check_password_hash
# Example: Creating a hashed password
plain_password = "mySecurePassword123"
hashed_password = generate_password_hash(plain_password, method='pbkdf2:sha256')
print("=" * 60)
print("PASSWORD HASHING DEMONSTRATION")
print("=" * 60)
print()
print(f"Original Password: {plain_password}")
print()
print(f"Hashed Password: {hashed_password}")
print()
print(f"Hash Length: {len(hashed_password)} characters")
print()
print("=" * 60)
print("SECURITY FEATURES")
print("=" * 60)
print("✓ Algorithm: PBKDF2-SHA256")
print("✓ Iterations: 600,000+")
print("✓ Unique salt per password")
print("✓ Cannot be reversed to plain text")
print("✓ Industry-standard security")
print()
print("=" * 60)
print("PASSWORD VERIFICATION TEST")
print("=" * 60)
print()
# Test correct password
correct = check_password_hash(hashed_password, "mySecurePassword123")
print(f"Testing correct password: {correct}")
# Test incorrect password
incorrect = check_password_hash(hashed_password, "wrongPassword")
print(f"Testing incorrect password: {incorrect}")
print()
# Show that the same password produces different hashes (due to unique salts)
print("=" * 60)
print("UNIQUE SALT DEMONSTRATION")
print("=" * 60)
print()
print("Hashing the same password twice produces different hashes:")
print()
hash1 = generate_password_hash("password123", method='pbkdf2:sha256')
hash2 = generate_password_hash("password123", method='pbkdf2:sha256')
print(f"Hash 1: {hash1}")
print(f"Hash 2: {hash2}")
print()
print(f"Are they different? {hash1 != hash2}")
print("Both hashes are valid and will verify correctly!")
print(f"Hash 1 verifies: {check_password_hash(hash1, 'password123')}")
print(f"Hash 2 verifies: {check_password_hash(hash2, 'password123')}")
print()
+46 -951
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
# Blueprint package
+253
View File
@@ -0,0 +1,253 @@
"""
Authentication Blueprint
Handles login, logout, and session management
"""
from flask import Blueprint, render_template, request, jsonify, session, redirect, url_for
from werkzeug.security import check_password_hash
from functools import wraps
import json
import os
auth_bp = Blueprint('auth', __name__)
# Path to users file
USERS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'users.json')
def load_users():
"""Load users from JSON file"""
if os.path.exists(USERS_FILE):
try:
with open(USERS_FILE, 'r') as f:
return json.load(f)
except:
return []
return []
def login_required(f):
"""Decorator to require login for routes"""
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_id' not in session:
return redirect(url_for('auth.login_page'))
# Check if user is active
users = load_users()
if session['user_id'] >= len(users):
session.clear()
return redirect(url_for('auth.login_page', message='User not found'))
user = users[session['user_id']]
if not user.get('active', True):
session.clear()
return redirect(url_for('auth.login_page', message='Account is inactive'))
return f(*args, **kwargs)
return decorated_function
def get_current_user():
"""Get the currently logged in user"""
if 'user_id' not in session:
return None
users = load_users()
if session['user_id'] >= len(users):
return None
return users[session['user_id']]
def can_user(permission, location=None):
"""
Check if current user has a specific permission.
Args:
permission (str): Permission name (e.g., 'manage_users')
location (str, optional): Check permission for specific location
Returns:
bool: True if user has permission
"""
user = get_current_user()
if not user:
return False
if not user.get('active', True):
return False
# Check global permissions
global_permissions = user.get('permissions', {})
if permission in global_permissions:
return global_permissions[permission] is True
if location == 'global':
return False
# Check location-specific permissions
check_location = location if location else session.get('currentLocation')
if not check_location:
return False
location_settings = user.get('locationSettings', {})
if check_location in location_settings:
loc_permissions = location_settings[check_location].get('permissions', {})
if permission in loc_permissions:
return loc_permissions[permission] is True
return False
# Routes
@auth_bp.route('/login')
def login_page():
"""Serve the login page"""
if 'user_id' in session:
return redirect(url_for('home'))
return render_template('login.html')
@auth_bp.route('/select-location')
def select_location_page():
"""Serve the location selection page"""
if 'user_id' not in session:
return redirect(url_for('auth.login_page'))
return render_template('select_location.html')
@auth_bp.route('/api/login', methods=['POST'])
def login():
"""Authenticate user and create session"""
try:
data = request.json
username = data.get('username')
password = data.get('password')
if not username or not password:
return jsonify({
'status': 'error',
'message': 'Username and password are required'
}), 400
users = load_users()
# Find user by username
user_index = None
user = None
for i, u in enumerate(users):
if u['username'] == username:
user_index = i
user = u
break
if not user:
return jsonify({
'status': 'error',
'message': 'Invalid username or password'
}), 401
# Check if user is active
if not user.get('active', True):
return jsonify({
'status': 'error',
'message': 'Account is inactive. Please contact an administrator.'
}), 403
# Verify password
if not check_password_hash(user['password'], password):
return jsonify({
'status': 'error',
'message': 'Invalid username or password'
}), 401
# Create session
session['user_id'] = user_index
session['username'] = user['username']
session['defaultLocation'] = user.get('defaultLocation')
# Get accessible locations
accessible_locations = []
if 'locationSettings' in user:
for loc_code, settings in user['locationSettings'].items():
if settings.get('accessible', False):
accessible_locations.append(loc_code)
session['accessibleLocations'] = accessible_locations
# Check if user needs to select a location
requiresLocationSelection = len(accessible_locations) > 1
# If only one location or no accessible locations, auto-select default
if not requiresLocationSelection:
session['currentLocation'] = user.get('defaultLocation')
return jsonify({
'status': 'success',
'message': 'Login successful',
'requiresLocationSelection': requiresLocationSelection
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@auth_bp.route('/api/select-location', methods=['POST'])
def select_location():
"""Select a location for the current session"""
if 'user_id' not in session:
return jsonify({
'status': 'error',
'message': 'Not logged in'
}), 401
try:
data = request.json
location = data.get('location')
# Verify user has access to this location
accessible = session.get('accessibleLocations', [])
if location not in accessible:
return jsonify({
'status': 'error',
'message': 'You do not have access to this location'
}), 403
session['currentLocation'] = location
return jsonify({
'status': 'success',
'message': 'Location selected',
'currentLocation': location
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@auth_bp.route('/logout')
def logout():
"""Log out user and clear session"""
session.clear()
return redirect(url_for('auth.login_page'))
@auth_bp.route('/api/session', methods=['GET'])
def get_session():
"""Get current session information"""
if 'user_id' not in session:
return jsonify({
'status': 'error',
'message': 'Not logged in'
}), 401
# Get user permissions
user = get_current_user()
permissions = {}
if user:
permissions = user.get('permissions', {})
return jsonify({
'status': 'success',
'username': session.get('username'),
'defaultLocation': session.get('defaultLocation'),
'currentLocation': session.get('currentLocation'),
'accessibleLocations': session.get('accessibleLocations', []),
'permissions': permissions
})
+38
View File
@@ -0,0 +1,38 @@
"""
Product Finder Blueprint
Handles the product quiz and recommendations
"""
from flask import Blueprint, render_template, send_from_directory
from blueprints.auth import login_required
import os
products_bp = Blueprint('products', __name__, url_prefix='/quiz')
# Get base directory
basedir = os.path.dirname(os.path.dirname(__file__))
@products_bp.route('/')
@login_required
def product_finder():
"""Serve the product finder quiz page"""
return render_template('product_finder.html')
@products_bp.route('/css/<path:filename>')
def serve_css(filename):
"""Serve CSS files"""
return send_from_directory(os.path.join(basedir, 'static', 'css'), filename)
@products_bp.route('/js/<path:filename>')
def serve_js(filename):
"""Serve JavaScript files"""
return send_from_directory(os.path.join(basedir, 'static', 'js'), filename)
@products_bp.route('/images/<path:filename>')
def serve_images(filename):
"""Serve image files"""
return send_from_directory(os.path.join(basedir, 'static', 'images'), filename)
@products_bp.route('/data/<path:filename>')
def serve_data(filename):
"""Serve data files (JSON)"""
return send_from_directory(os.path.join(basedir, 'data'), filename)
+277
View File
@@ -0,0 +1,277 @@
"""
User Management Blueprint
Handles user CRUD operations
"""
from flask import Blueprint, render_template, request, jsonify, send_file, session
from werkzeug.security import generate_password_hash, check_password_hash
from blueprints.auth import login_required, can_user, get_current_user
from io import BytesIO
import json
import os
users_bp = Blueprint('users', __name__, url_prefix='/users')
# Path to users file
USERS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'users.json')
def load_users():
"""Load users from JSON file"""
if os.path.exists(USERS_FILE):
try:
with open(USERS_FILE, 'r') as f:
return json.load(f)
except:
return []
return []
def save_users(users):
"""Save users to JSON file"""
os.makedirs(os.path.dirname(USERS_FILE), exist_ok=True)
with open(USERS_FILE, 'w') as f:
json.dump(users, f, indent=2)
def permission_required(permission):
"""Decorator to require specific permission"""
from functools import wraps
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not can_user(permission):
return jsonify({
'status': 'error',
'message': 'Permission denied'
}), 403
return f(*args, **kwargs)
return decorated_function
return decorator
# Routes
@users_bp.route('/')
@login_required
def user_manager():
"""Serve the user management page"""
if not can_user('manage_users'):
return "<h1>403 - Permission Denied</h1><p>You don't have permission to manage users.</p>", 403
current_user_id = session.get('user_id', -1)
return render_template('user_manager.html', current_user_id=current_user_id)
@users_bp.route('/api', methods=['GET'])
@login_required
@permission_required('manage_users')
def get_users():
"""Get all users"""
users = load_users()
return jsonify({
'status': 'success',
'users': users
})
@users_bp.route('/api', methods=['POST'])
@login_required
@permission_required('manage_users')
def add_user():
"""Add a new user with hashed password"""
try:
data = request.json
# Validate required fields
if not data.get('username') or not data.get('password') or not data.get('defaultLocation'):
return jsonify({
'status': 'error',
'message': 'Username, password, and default location are required'
}), 400
users = load_users()
# Check if username already exists
if any(user['username'] == data['username'] for user in users):
return jsonify({
'status': 'error',
'message': 'Username already exists'
}), 400
# Hash the password
hashed_password = generate_password_hash(data['password'], method='pbkdf2:sha256')
# Get location settings
location_settings = data.get('locationSettings', {})
default_location = data['defaultLocation']
# Ensure default location is accessible
if default_location not in location_settings:
location_settings[default_location] = {}
location_settings[default_location]['accessible'] = True
# Create new user
new_user = {
'username': data['username'],
'password': hashed_password,
'defaultLocation': default_location,
'locationSettings': location_settings,
'permissions': data.get('permissions', {}),
'active': data.get('active', True)
}
users.append(new_user)
save_users(users)
return jsonify({
'status': 'success',
'message': 'User added successfully',
'users': users
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@users_bp.route('/api/<int:user_index>', methods=['DELETE'])
@login_required
@permission_required('manage_users')
def delete_user(user_index):
"""Delete a specific user by index"""
try:
users = load_users()
if user_index < 0 or user_index >= len(users):
return jsonify({
'status': 'error',
'message': 'Invalid user index'
}), 400
users.pop(user_index)
save_users(users)
return jsonify({
'status': 'success',
'message': 'User deleted successfully',
'users': users
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@users_bp.route('/api/<int:user_index>/active', methods=['PATCH'])
@login_required
@permission_required('manage_users')
def toggle_user_active(user_index):
"""Toggle user active status"""
try:
data = request.json
users = load_users()
if user_index < 0 or user_index >= len(users):
return jsonify({
'status': 'error',
'message': 'Invalid user index'
}), 400
users[user_index]['active'] = data.get('active', True)
save_users(users)
return jsonify({
'status': 'success',
'message': 'User status updated',
'users': users
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@users_bp.route('/api/<int:user_index>/change-password', methods=['POST'])
@login_required
@permission_required('manage_users')
def change_user_password(user_index):
"""Change a user's password with current user verification"""
try:
data = request.json
new_password = data.get('newPassword')
current_user_password = data.get('currentUserPassword')
if not new_password or not current_user_password:
return jsonify({
'status': 'error',
'message': 'New password and current user password are required'
}), 400
if len(new_password) < 6:
return jsonify({
'status': 'error',
'message': 'Password must be at least 6 characters long'
}), 400
# Verify current user's password
current_user = get_current_user()
if not current_user:
return jsonify({
'status': 'error',
'message': 'Not authenticated'
}), 401
if not check_password_hash(current_user['password'], current_user_password):
return jsonify({
'status': 'error',
'message': 'Your password is incorrect. Password change denied for security reasons.'
}), 403
# Load users and validate index
users = load_users()
if user_index < 0 or user_index >= len(users):
return jsonify({
'status': 'error',
'message': 'Invalid user index'
}), 400
# Update password
hashed_password = generate_password_hash(new_password, method='pbkdf2:sha256')
target_username = users[user_index]['username']
users[user_index]['password'] = hashed_password
save_users(users)
return jsonify({
'status': 'success',
'message': f'Password changed successfully for user "{target_username}"'
})
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@users_bp.route('/api/download')
@login_required
@permission_required('manage_users')
def download_users():
"""Download users as JSON file"""
try:
users = load_users()
if not users:
return jsonify({
'status': 'error',
'message': 'No users to download'
}), 400
json_data = json.dumps(users, indent=2)
return send_file(
BytesIO(json_data.encode()),
mimetype='application/json',
as_attachment=True,
download_name='users.json'
)
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

-44
View File
@@ -1,44 +0,0 @@
"""
Configuration file for Flask application
"""
import os
class Config:
"""Base configuration"""
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-change-in-production'
DEBUG = False
TESTING = False
# Application root for subdirectory deployments
# Defaults to '/' (root) for local development
# Set to '/product-finder' for production deployment
APPLICATION_ROOT = os.environ.get('APPLICATION_ROOT', '/')
class DevelopmentConfig(Config):
"""Development configuration"""
DEBUG = True
ENV = 'development'
# Development runs at root
APPLICATION_ROOT = os.environ.get('APPLICATION_ROOT', '/')
class ProductionConfig(Config):
"""Production configuration"""
DEBUG = False
ENV = 'production'
# Production deployed to /product-finder subdirectory
APPLICATION_ROOT = os.environ.get('APPLICATION_ROOT', '/product-finder')
# Add production-specific settings here
# DATABASE_URI = os.environ.get('DATABASE_URL')
class TestingConfig(Config):
"""Testing configuration"""
TESTING = True
DEBUG = True
# Configuration dictionary
config = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'testing': TestingConfig,
'default': DevelopmentConfig
}
-40
View File
@@ -1,40 +0,0 @@
{
"description": "Bitwise flag system for product classification",
"bit_definitions": {
"base_attributes": {
"bit_0 (1)": "Base Type = Door",
"bit_1 (2)": "Base Type = Window",
"bit_2 (4)": "Is Accessory",
"bit_3 (8)": "Specific Item Link"
},
"materials": {
"bit_4 (16)": "Material = Aluminum",
"bit_5 (32)": "Material = Vinyl"
},
"colors": {
"bit_6 (64)": "Color = Black",
"bit_7 (128)": "Color = White",
"bit_8 (256)": "Color = Bronze",
"bit_9 (512)": "Color = Tan",
"bit_10 (1024)": "Color = Mill",
"bit_11 (2048)": "Color = Sandstone"
},
"subtypes": {
"bit_12 (4096)": "Subtype = Patio Door",
"bit_13 (8192)": "Subtype = Primary Window",
"bit_14 (16384)": "Subtype = Storm Door",
"bit_15 (32768)": "Subtype = Storm Window"
}
},
"usage_examples": {
"check_if_door": "bit_value & 1",
"check_if_window": "bit_value & 2",
"check_if_aluminum": "bit_value & 16",
"check_if_white": "bit_value & 128",
"check_multiple": "(bit_value & 1) and (bit_value & 16) # Door AND Aluminum",
"check_subtype_patio_door": "bit_value & 4096",
"check_subtype_primary_window": "bit_value & 8192",
"check_subtype_storm_door": "bit_value & 16384",
"check_subtype_storm_window": "bit_value & 32768"
}
}
-15
View File
@@ -1,15 +0,0 @@
Product_Name,Image_URL,Product_Type,Notes
Brass Lever,http://columbiawindows.com/wp-content/uploads/2014/12/CR2DLEC.jpg,Hardware,
Brass Lever (White),http://columbiawindows.com/wp-content/uploads/2014/12/CR2DLEC.jpg,Hardware,Also comes in white
Brass Lever (MT Gold),http://columbiawindows.com/wp-content/uploads/2014/12/MT-MET-GOLD.jpg,Hardware,
Brass Lever (550 Gold),http://columbiawindows.com/wp-content/uploads/2014/12/550-met-gold.jpg,Hardware,
Brass Pull,http://columbiawindows.com/wp-content/uploads/2014/12/dx-ecoat.jpg,Hardware,
Brass Pull (White),http://columbiawindows.com/wp-content/uploads/2014/12/CR3SEC.jpg,Hardware,Also comes in white
Brass Pull (MT Gold),http://columbiawindows.com/wp-content/uploads/2014/12/MT-MET-GOLD.jpg,Hardware,
Brass Pull (550 Gold),http://columbiawindows.com/wp-content/uploads/2014/12/550-met-gold.jpg,Hardware,
Satin Pull,http://columbiawindows.com/wp-content/uploads/2014/12/dx-satin-finish.jpg,Hardware,
Satin Pull (Silver),http://columbiawindows.com/wp-content/uploads/2014/12/MT-satin-silver.jpg,Hardware,
Black Pull Handle,http://columbiawindows.com/wp-content/uploads/2014/12/VPBLACK.jpg,Hardware,
White Pull Handle,http://columbiawindows.com/wp-content/uploads/2014/12/VPWHITE.jpg,Hardware,
Bevel Cut Insert,http://columbiawindows.com/wp-content/uploads/2014/12/bevel.jpg,Insert,
Brass Kick Panel,http://columbiawindows.com/wp-content/uploads/2014/12/brasskp.jpg,Panel,
1 Product_Name Image_URL Product_Type Notes
2 Brass Lever http://columbiawindows.com/wp-content/uploads/2014/12/CR2DLEC.jpg Hardware
3 Brass Lever (White) http://columbiawindows.com/wp-content/uploads/2014/12/CR2DLEC.jpg Hardware Also comes in white
4 Brass Lever (MT Gold) http://columbiawindows.com/wp-content/uploads/2014/12/MT-MET-GOLD.jpg Hardware
5 Brass Lever (550 Gold) http://columbiawindows.com/wp-content/uploads/2014/12/550-met-gold.jpg Hardware
6 Brass Pull http://columbiawindows.com/wp-content/uploads/2014/12/dx-ecoat.jpg Hardware
7 Brass Pull (White) http://columbiawindows.com/wp-content/uploads/2014/12/CR3SEC.jpg Hardware Also comes in white
8 Brass Pull (MT Gold) http://columbiawindows.com/wp-content/uploads/2014/12/MT-MET-GOLD.jpg Hardware
9 Brass Pull (550 Gold) http://columbiawindows.com/wp-content/uploads/2014/12/550-met-gold.jpg Hardware
10 Satin Pull http://columbiawindows.com/wp-content/uploads/2014/12/dx-satin-finish.jpg Hardware
11 Satin Pull (Silver) http://columbiawindows.com/wp-content/uploads/2014/12/MT-satin-silver.jpg Hardware
12 Black Pull Handle http://columbiawindows.com/wp-content/uploads/2014/12/VPBLACK.jpg Hardware
13 White Pull Handle http://columbiawindows.com/wp-content/uploads/2014/12/VPWHITE.jpg Hardware
14 Bevel Cut Insert http://columbiawindows.com/wp-content/uploads/2014/12/bevel.jpg Insert
15 Brass Kick Panel http://columbiawindows.com/wp-content/uploads/2014/12/brasskp.jpg Panel
-68
View File
@@ -1,68 +0,0 @@
[
{
"username": "admin_user",
"password": "pbkdf2:sha256:1000000$examplehash$...",
"defaultLocation": "LINDS",
"active": true,
"permissions": {
"manage_users": true,
"view_reports": true,
"create_quotes": true
},
"locationSettings": {
"LINDS": {
"accessible": true,
"permissions": {
"manage_inventory": true,
"approve_quotes": true
}
},
"IOLA": {
"accessible": true,
"permissions": {
"manage_inventory": false,
"approve_quotes": true
}
},
"KC": {
"accessible": false
},
"BMD": {
"accessible": false
}
}
},
{
"username": "standard_user",
"password": "pbkdf2:sha256:1000000$examplehash2$...",
"defaultLocation": "KC",
"active": true,
"permissions": {
"manage_users": false,
"view_reports": true,
"create_quotes": true
},
"locationSettings": {
"LINDS": {
"accessible": true,
"permissions": {
"manage_inventory": false,
"approve_quotes": false
}
},
"IOLA": {
"accessible": true
},
"KC": {
"accessible": true,
"permissions": {
"manage_inventory": false,
"approve_quotes": false
}
},
"BMD": {
"accessible": true
}
}
}
]
-94
View File
@@ -1,94 +0,0 @@
{
"cobrai": {
"sourceImage": "images/cobrai",
"productCode": "COBRAI",
"description": "Storm Door - Full View with Screen",
"availableColors": {
"white": {"rgb": [255, 255, 255], "name": "White"},
"black": {"rgb": [30, 30, 30], "name": "Black"},
"bronze": {"rgb": [110, 80, 50], "name": "Bronze"},
"sandstone": {"rgb": [210, 190, 165], "name": "Sandstone"}
},
"colorableRegions": [
{
"name": "region_name",
"topLeft": [24, 23],
"bottomRight": [505, 1022],
"description": "Width: 481px, Height: 999px"
},
{
"name": "frame",
"topLeft": [0, 0],
"bottomRight": [100, 1450],
"description": "Vertical frame left side"
},
{
"name": "frame_right",
"topLeft": [620, 0],
"bottomRight": [720, 1450],
"description": "Vertical frame right side"
},
{
"name": "top_rail",
"topLeft": [0, 0],
"bottomRight": [720, 80],
"description": "Top horizontal rail"
},
{
"name": "mid_rail",
"topLeft": [0, 590],
"bottomRight": [720, 680],
"description": "Middle horizontal rail"
},
{
"name": "bottom_panel",
"topLeft": [100, 1090],
"bottomRight": [620, 1450],
"description": "Bottom kickplate panel"
}
],
"hardwarePositions": {
"handle_right": {
"x": 580,
"y": 730,
"image": "images/hardware/handle-lever.png"
},
"handle_left": {
"x": 140,
"y": 730,
"image": "images/hardware/handle-lever.png",
"flip": true
},
"lock": {
"x": 360,
"y": 800,
"image": "images/hardware/lock.png"
}
},
"glassRegions": [
{
"name": "top_glass",
"topLeft": [100, 80],
"bottomRight": [620, 590],
"description": "Top screen/glass area"
},
{
"name": "bottom_glass",
"topLeft": [100, 680],
"bottomRight": [620, 1090],
"description": "Bottom screen/glass area"
}
],
"metadata": {
"imageWidth": 720,
"imageHeight": 1450,
"defaultColor": "white",
"defaultHinge": "right"
},
"cache": {
"enabled": true,
"directory": "cache/product_images",
"maxAge": 86400
}
}
}
-922
View File
@@ -1,922 +0,0 @@
PROD_CODE,BIT_VALUE,BIT_HEX,BIT_BINARY,DISCONTINUED,FLAGS
1650-10,16,0x10,10000,False,Aluminum
404,35282,0x89D2,1000100111010010,False,Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
450,35282,0x89D2,1000100111010010,False,Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
606,35282,0x89D2,1000100111010010,False,Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
650,33234,0x81D2,1000000111010010,False,Window | Aluminum | Black | White | Bronze | Subtype:Storm Window
1400,160,0xA0,10100000,False,Vinyl | White
1500,8354,0x20A2,10000010100010,False,Window | Vinyl | White | Subtype:Primary Window
1510,160,0xA0,10100000,False,Vinyl | White
1650,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1710,16,0x10,10000,False,Aluminum
2000,8594,0x2192,10000110010010,False,Window | Aluminum | White | Bronze | Subtype:Primary Window
2100,16,0x10,10000,False,Aluminum
2200,16,0x10,10000,False,Aluminum
2650,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2700,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2710,16,0x10,10000,False,Aluminum
3000,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
3100,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
3200,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
3300,400,0x190,110010000,False,Aluminum | White | Bronze
3302,400,0x190,110010000,False,Aluminum | White | Bronze
3303,400,0x190,110010000,False,Aluminum | White | Bronze
3310,400,0x190,110010000,False,Aluminum | White | Bronze
3700,400,0x190,110010000,False,Aluminum | White | Bronze
3710,16,0x10,10000,False,Aluminum
4700,400,0x190,110010000,False,Aluminum | White | Bronze
4710,16,0x10,10000,False,Aluminum
5200,4769,0x12A1,1001010100001,False,Door | Vinyl | White | Tan | Subtype:Patio Door
5700,400,0x190,110010000,False,Aluminum | White | Bronze
6700,16,0x10,10000,False,Aluminum
265010,16,0x10,10000,False,Aluminum
1400SCR,144,0x90,10010000,False,Aluminum | White
1650SCR,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1650VS,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700CSC,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700CV,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700ESC,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700EV,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700SCR,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
1700VS,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2000SCR,400,0x190,110010000,False,Aluminum | White | Bronze
2100EV,400,0x190,110010000,False,Aluminum | White | Bronze
2200PDG,16,0x10,10000,False,Aluminum
2650SCR,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2650VP,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2700CV,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2700EV,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2700SCR,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
2700VS,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
3000SCR,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
305INS,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
306INS,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
3100EV,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
3100SCR,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
310PSCR,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
3700SCR,400,0x190,110010000,False,Aluminum | White | Bronze
3700VP,400,0x190,110010000,False,Aluminum | White | Bronze
404ONE,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
450ONE,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
4700SCR,400,0x190,110010000,False,Aluminum | White | Bronze
606ONE,1488,0x5D0,10111010000,False,Aluminum | Black | White | Bronze | Mill
6100I,16785,0x4191,100000110010001,False,Door | Aluminum | White | Bronze | Subtype:Storm Door
650ONE,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
8100I,16785,0x4191,100000110010001,False,Door | Aluminum | White | Bronze | Subtype:Storm Door
BELMONT,672,0x2A0,1010100000,False,Vinyl | White | Tan
BGI,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
BGI404,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
BGI606,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
BGIST,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
C-500,2448,0x990,100110010000,False,Aluminum | White | Bronze | Sandstone
C1150,160,0xA0,10100000,False,Vinyl | White
C1621,16,0x10,10000,False,Aluminum
C1622,16,0x10,10000,False,Aluminum
C1626VA,16,0x10,10000,False,Aluminum
C1710,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
C1721,16,0x10,10000,False,Aluminum
C1722,16,0x10,10000,False,Aluminum
C1724,16,0x10,10000,False,Aluminum
C1800,33170,0x8192,1000000110010010,False,Window | Aluminum | White | Bronze | Subtype:Storm Window
C2021,16,0x10,10000,False,Aluminum
C2022,16,0x10,10000,False,Aluminum
C2026,16,0x10,10000,False,Aluminum
C2710,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
C300,16,0x10,10000,False,Aluminum
C3221,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
C3222,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
C3223,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
C3224,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
C3300,400,0x190,110010000,False,Aluminum | White | Bronze
C3700,16,0x10,10000,False,Aluminum
C400,160,0xA0,10100000,False,Vinyl | White
C500,2448,0x990,100110010000,False,Aluminum | White | Bronze | Sandstone
C500GL,0,0x0,0,False,None
C500GLP,0,0x0,0,False,None
C500PP,2448,0x990,100110010000,False,Aluminum | White | Bronze | Sandstone
C500SCR,2448,0x990,100110010000,False,Aluminum | White | Bronze | Sandstone
C500VP,2448,0x990,100110010000,False,Aluminum | White | Bronze | Sandstone
C521,400,0x190,110010000,False,Aluminum | White | Bronze
C522,400,0x190,110010000,False,Aluminum | White | Bronze
C526,400,0x190,110010000,False,Aluminum | White | Bronze
C900,400,0x190,110010000,False,Aluminum | White | Bronze
C900EV,400,0x190,110010000,False,Aluminum | White | Bronze
C900SCR,400,0x190,110010000,False,Aluminum | White | Bronze
C910,16,0x10,10000,False,Aluminum
C910PP,16,0x10,10000,False,Aluminum
C921,400,0x190,110010000,False,Aluminum | White | Bronze
C922,400,0x190,110010000,False,Aluminum | White | Bronze
C924,400,0x190,110010000,False,Aluminum | White | Bronze
C931,400,0x190,110010000,False,Aluminum | White | Bronze
C939,400,0x190,110010000,False,Aluminum | White | Bronze
C940,400,0x190,110010000,False,Aluminum | White | Bronze
C949,400,0x190,110010000,False,Aluminum | White | Bronze
C960,16,0x10,10000,False,Aluminum
COBRAI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
COBRATI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
CRWNFVI,16401,0x4011,100000000010001,False,Door | Aluminum | Subtype:Storm Door
CRWNSDI,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
D770,8354,0x20A2,10000010100010,False,Window | Vinyl | White | Subtype:Primary Window
DSGLASS,0,0x0,0,False,None
DURASEA,0,0x0,0,False,None
EXPAND,16,0x10,10000,False,Aluminum
FULLSCR,16,0x10,10000,False,Aluminum
FVGI,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
FVSI,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
GOLIATH,16401,0x4011,100000000010001,False,Door | Aluminum | Subtype:Storm Door
HERCULE,16401,0x4011,100000000010001,False,Door | Aluminum | Subtype:Storm Door
IMPERIL,4561,0x11D1,1000111010001,False,Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
INSGLAS,0,0x0,0,False,None
ISP,464,0x1D0,111010000,False,Aluminum | Black | White | Bronze
IVP,4561,0x11D1,1000111010001,False,Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
JET,4497,0x1191,1000110010001,False,Door | Aluminum | White | Bronze | Subtype:Patio Door
JSP,400,0x190,110010000,False,Aluminum | White | Bronze
JVP,4497,0x1191,1000110010001,False,Door | Aluminum | White | Bronze | Subtype:Patio Door
KINGDVI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
KINGFSC,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
KINGI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
KINGSDI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
M1200,4497,0x1191,1000110010001,False,Door | Aluminum | White | Bronze | Subtype:Patio Door
M306,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
OUTSIDE,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
PATIOSC,6609,0x19D1,1100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Patio Door
PDSCRTT,6609,0x19D1,1100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Patio Door
PRPDS,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
PRSCR,3984,0xF90,111110010000,False,Aluminum | White | Bronze | Tan | Mill | Sandstone
PRSCR11,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
PSINS,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
PWS,4048,0xFD0,111111010000,False,Aluminum | Black | White | Bronze | Tan | Mill | Sandstone
PWSINS,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
R1150,160,0xA0,10100000,False,Vinyl | White
R1400,8354,0x20A2,10000010100010,False,Window | Vinyl | White | Subtype:Primary Window
R1500,8354,0x20A2,10000010100010,False,Window | Vinyl | White | Subtype:Primary Window
R1510,32,0x20,100000,False,Vinyl
R2000,8594,0x2192,10000110010010,False,Window | Aluminum | White | Bronze | Subtype:Primary Window
R2100,400,0x190,110010000,False,Aluminum | White | Bronze
R2100EV,400,0x190,110010000,False,Aluminum | White | Bronze
R2200,400,0x190,110010000,False,Aluminum | White | Bronze
R300,16,0x10,10000,False,Aluminum
R3302,400,0x190,110010000,False,Aluminum | White | Bronze
R400,160,0xA0,10100000,False,Vinyl | White
R770,8354,0x20A2,10000010100010,False,Window | Vinyl | White | Subtype:Primary Window
R770SCR,16,0x10,10000,False,Aluminum
RCKTRAP,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
REWIRE,16,0x10,10000,False,Aluminum
RNDROCK,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
ROCKET,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
RROCKET,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
SCRI,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
SCRI404,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
SCRI606,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
SCRI808,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
SSGLASS,0,0x0,0,False,None
SSSCR,16,0x10,10000,False,Aluminum
TBGI,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
TBR,4561,0x11D1,1000111010001,False,Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
TGI,1424,0x590,10110010000,False,Aluminum | White | Bronze | Mill
TGI404,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
TGI606,3536,0xDD0,110111010000,False,Aluminum | Black | White | Bronze | Mill | Sandstone
TGIODD,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
THOR,16401,0x4011,100000000010001,False,Door | Aluminum | Subtype:Storm Door
TVI,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
VKI,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
VP3700,400,0x190,110010000,False,Aluminum | White | Bronze
WINDGAT,672,0x2A0,1010100000,False,Vinyl | White | Tan
ZBARS,2512,0x9D0,100111010000,False,Aluminum | Black | White | Bronze | Sandstone
COBRATK,18897,0x49D1,100100111010001,False,Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
,0,0x0,0,False,None
1 PROD_CODE BIT_VALUE BIT_HEX BIT_BINARY DISCONTINUED FLAGS
2 1650-10 16 0x10 10000 False Aluminum
3 404 35282 0x89D2 1000100111010010 False Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
4 450 35282 0x89D2 1000100111010010 False Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
5 606 35282 0x89D2 1000100111010010 False Window | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Window
6 650 33234 0x81D2 1000000111010010 False Window | Aluminum | Black | White | Bronze | Subtype:Storm Window
7 1400 160 0xA0 10100000 False Vinyl | White
8 1500 8354 0x20A2 10000010100010 False Window | Vinyl | White | Subtype:Primary Window
9 1510 160 0xA0 10100000 False Vinyl | White
10 1650 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
11 1700 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
12 1710 16 0x10 10000 False Aluminum
13 2000 8594 0x2192 10000110010010 False Window | Aluminum | White | Bronze | Subtype:Primary Window
14 2100 16 0x10 10000 False Aluminum
15 2200 16 0x10 10000 False Aluminum
16 2650 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
17 2700 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
18 2710 16 0x10 10000 False Aluminum
19 3000 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
20 3100 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
21 3200 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
22 3300 400 0x190 110010000 False Aluminum | White | Bronze
23 3302 400 0x190 110010000 False Aluminum | White | Bronze
24 3303 400 0x190 110010000 False Aluminum | White | Bronze
25 3310 400 0x190 110010000 False Aluminum | White | Bronze
26 3700 400 0x190 110010000 False Aluminum | White | Bronze
27 3710 16 0x10 10000 False Aluminum
28 4700 400 0x190 110010000 False Aluminum | White | Bronze
29 4710 16 0x10 10000 False Aluminum
30 5200 4769 0x12A1 1001010100001 False Door | Vinyl | White | Tan | Subtype:Patio Door
31 5700 400 0x190 110010000 False Aluminum | White | Bronze
32 6700 16 0x10 10000 False Aluminum
33 265010 16 0x10 10000 False Aluminum
34 1400SCR 144 0x90 10010000 False Aluminum | White
35 1650SCR 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
36 1650VS 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
37 1700CSC 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
38 1700CV 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
39 1700ESC 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
40 1700EV 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
41 1700SCR 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
42 1700VS 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
43 2000SCR 400 0x190 110010000 False Aluminum | White | Bronze
44 2100EV 400 0x190 110010000 False Aluminum | White | Bronze
45 2200PDG 16 0x10 10000 False Aluminum
46 2650SCR 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
47 2650VP 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
48 2700CV 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
49 2700EV 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
50 2700SCR 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
51 2700VS 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
52 3000SCR 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
53 305INS 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
54 306INS 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
55 3100EV 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
56 3100SCR 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
57 310PSCR 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
58 3700SCR 400 0x190 110010000 False Aluminum | White | Bronze
59 3700VP 400 0x190 110010000 False Aluminum | White | Bronze
60 404ONE 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
61 450ONE 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
62 4700SCR 400 0x190 110010000 False Aluminum | White | Bronze
63 606ONE 1488 0x5D0 10111010000 False Aluminum | Black | White | Bronze | Mill
64 6100I 16785 0x4191 100000110010001 False Door | Aluminum | White | Bronze | Subtype:Storm Door
65 650ONE 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
66 8100I 16785 0x4191 100000110010001 False Door | Aluminum | White | Bronze | Subtype:Storm Door
67 BELMONT 672 0x2A0 1010100000 False Vinyl | White | Tan
68 BGI 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
69 BGI404 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
70 BGI606 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
71 BGIST 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
72 C-500 2448 0x990 100110010000 False Aluminum | White | Bronze | Sandstone
73 C1150 160 0xA0 10100000 False Vinyl | White
74 C1621 16 0x10 10000 False Aluminum
75 C1622 16 0x10 10000 False Aluminum
76 C1626VA 16 0x10 10000 False Aluminum
77 C1710 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
78 C1721 16 0x10 10000 False Aluminum
79 C1722 16 0x10 10000 False Aluminum
80 C1724 16 0x10 10000 False Aluminum
81 C1800 33170 0x8192 1000000110010010 False Window | Aluminum | White | Bronze | Subtype:Storm Window
82 C2021 16 0x10 10000 False Aluminum
83 C2022 16 0x10 10000 False Aluminum
84 C2026 16 0x10 10000 False Aluminum
85 C2710 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
86 C300 16 0x10 10000 False Aluminum
87 C3221 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
88 C3222 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
89 C3223 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
90 C3224 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
91 C3300 400 0x190 110010000 False Aluminum | White | Bronze
92 C3700 16 0x10 10000 False Aluminum
93 C400 160 0xA0 10100000 False Vinyl | White
94 C500 2448 0x990 100110010000 False Aluminum | White | Bronze | Sandstone
95 C500GL 0 0x0 0 False None
96 C500GLP 0 0x0 0 False None
97 C500PP 2448 0x990 100110010000 False Aluminum | White | Bronze | Sandstone
98 C500SCR 2448 0x990 100110010000 False Aluminum | White | Bronze | Sandstone
99 C500VP 2448 0x990 100110010000 False Aluminum | White | Bronze | Sandstone
100 C521 400 0x190 110010000 False Aluminum | White | Bronze
101 C522 400 0x190 110010000 False Aluminum | White | Bronze
102 C526 400 0x190 110010000 False Aluminum | White | Bronze
103 C900 400 0x190 110010000 False Aluminum | White | Bronze
104 C900EV 400 0x190 110010000 False Aluminum | White | Bronze
105 C900SCR 400 0x190 110010000 False Aluminum | White | Bronze
106 C910 16 0x10 10000 False Aluminum
107 C910PP 16 0x10 10000 False Aluminum
108 C921 400 0x190 110010000 False Aluminum | White | Bronze
109 C922 400 0x190 110010000 False Aluminum | White | Bronze
110 C924 400 0x190 110010000 False Aluminum | White | Bronze
111 C931 400 0x190 110010000 False Aluminum | White | Bronze
112 C939 400 0x190 110010000 False Aluminum | White | Bronze
113 C940 400 0x190 110010000 False Aluminum | White | Bronze
114 C949 400 0x190 110010000 False Aluminum | White | Bronze
115 C960 16 0x10 10000 False Aluminum
116 COBRAI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
117 COBRATI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
118 CRWNFVI 16401 0x4011 100000000010001 False Door | Aluminum | Subtype:Storm Door
119 CRWNSDI 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
120 D770 8354 0x20A2 10000010100010 False Window | Vinyl | White | Subtype:Primary Window
121 DSGLASS 0 0x0 0 False None
122 DURASEA 0 0x0 0 False None
123 EXPAND 16 0x10 10000 False Aluminum
124 FULLSCR 16 0x10 10000 False Aluminum
125 FVGI 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
126 FVSI 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
127 GOLIATH 16401 0x4011 100000000010001 False Door | Aluminum | Subtype:Storm Door
128 HERCULE 16401 0x4011 100000000010001 False Door | Aluminum | Subtype:Storm Door
129 IMPERIL 4561 0x11D1 1000111010001 False Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
130 INSGLAS 0 0x0 0 False None
131 ISP 464 0x1D0 111010000 False Aluminum | Black | White | Bronze
132 IVP 4561 0x11D1 1000111010001 False Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
133 JET 4497 0x1191 1000110010001 False Door | Aluminum | White | Bronze | Subtype:Patio Door
134 JSP 400 0x190 110010000 False Aluminum | White | Bronze
135 JVP 4497 0x1191 1000110010001 False Door | Aluminum | White | Bronze | Subtype:Patio Door
136 KINGDVI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
137 KINGFSC 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
138 KINGI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
139 KINGSDI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
140 M1200 4497 0x1191 1000110010001 False Door | Aluminum | White | Bronze | Subtype:Patio Door
141 M306 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
142 OUTSIDE 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
143 PATIOSC 6609 0x19D1 1100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Patio Door
144 PDSCRTT 6609 0x19D1 1100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Patio Door
145 PRPDS 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
146 PRSCR 3984 0xF90 111110010000 False Aluminum | White | Bronze | Tan | Mill | Sandstone
147 PRSCR11 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
148 PSINS 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
149 PWS 4048 0xFD0 111111010000 False Aluminum | Black | White | Bronze | Tan | Mill | Sandstone
150 PWSINS 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
151 R1150 160 0xA0 10100000 False Vinyl | White
152 R1400 8354 0x20A2 10000010100010 False Window | Vinyl | White | Subtype:Primary Window
153 R1500 8354 0x20A2 10000010100010 False Window | Vinyl | White | Subtype:Primary Window
154 R1510 32 0x20 100000 False Vinyl
155 R2000 8594 0x2192 10000110010010 False Window | Aluminum | White | Bronze | Subtype:Primary Window
156 R2100 400 0x190 110010000 False Aluminum | White | Bronze
157 R2100EV 400 0x190 110010000 False Aluminum | White | Bronze
158 R2200 400 0x190 110010000 False Aluminum | White | Bronze
159 R300 16 0x10 10000 False Aluminum
160 R3302 400 0x190 110010000 False Aluminum | White | Bronze
161 R400 160 0xA0 10100000 False Vinyl | White
162 R770 8354 0x20A2 10000010100010 False Window | Vinyl | White | Subtype:Primary Window
163 R770SCR 16 0x10 10000 False Aluminum
164 RCKTRAP 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
165 REWIRE 16 0x10 10000 False Aluminum
166 RNDROCK 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
167 ROCKET 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
168 RROCKET 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
169 SCRI 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
170 SCRI404 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
171 SCRI606 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
172 SCRI808 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
173 SSGLASS 0 0x0 0 False None
174 SSSCR 16 0x10 10000 False Aluminum
175 TBGI 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
176 TBR 4561 0x11D1 1000111010001 False Door | Aluminum | Black | White | Bronze | Subtype:Patio Door
177 TGI 1424 0x590 10110010000 False Aluminum | White | Bronze | Mill
178 TGI404 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
179 TGI606 3536 0xDD0 110111010000 False Aluminum | Black | White | Bronze | Mill | Sandstone
180 TGIODD 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
181 THOR 16401 0x4011 100000000010001 False Door | Aluminum | Subtype:Storm Door
182 TVI 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
183 VKI 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
184 VP3700 400 0x190 110010000 False Aluminum | White | Bronze
185 WINDGAT 672 0x2A0 1010100000 False Vinyl | White | Tan
186 ZBARS 2512 0x9D0 100111010000 False Aluminum | Black | White | Bronze | Sandstone
187 COBRATK 18897 0x49D1 100100111010001 False Door | Aluminum | Black | White | Bronze | Sandstone | Subtype:Storm Door
188 0 0x0 0 False None
189 0 0x0 0 False None
190 0 0x0 0 False None
191 0 0x0 0 False None
192 0 0x0 0 False None
193 0 0x0 0 False None
194 0 0x0 0 False None
195 0 0x0 0 False None
196 0 0x0 0 False None
197 0 0x0 0 False None
198 0 0x0 0 False None
199 0 0x0 0 False None
200 0 0x0 0 False None
201 0 0x0 0 False None
202 0 0x0 0 False None
203 0 0x0 0 False None
204 0 0x0 0 False None
205 0 0x0 0 False None
206 0 0x0 0 False None
207 0 0x0 0 False None
208 0 0x0 0 False None
209 0 0x0 0 False None
210 0 0x0 0 False None
211 0 0x0 0 False None
212 0 0x0 0 False None
213 0 0x0 0 False None
214 0 0x0 0 False None
215 0 0x0 0 False None
216 0 0x0 0 False None
217 0 0x0 0 False None
218 0 0x0 0 False None
219 0 0x0 0 False None
220 0 0x0 0 False None
221 0 0x0 0 False None
222 0 0x0 0 False None
223 0 0x0 0 False None
224 0 0x0 0 False None
225 0 0x0 0 False None
226 0 0x0 0 False None
227 0 0x0 0 False None
228 0 0x0 0 False None
229 0 0x0 0 False None
230 0 0x0 0 False None
231 0 0x0 0 False None
232 0 0x0 0 False None
233 0 0x0 0 False None
234 0 0x0 0 False None
235 0 0x0 0 False None
236 0 0x0 0 False None
237 0 0x0 0 False None
238 0 0x0 0 False None
239 0 0x0 0 False None
240 0 0x0 0 False None
241 0 0x0 0 False None
242 0 0x0 0 False None
243 0 0x0 0 False None
244 0 0x0 0 False None
245 0 0x0 0 False None
246 0 0x0 0 False None
247 0 0x0 0 False None
248 0 0x0 0 False None
249 0 0x0 0 False None
250 0 0x0 0 False None
251 0 0x0 0 False None
252 0 0x0 0 False None
253 0 0x0 0 False None
254 0 0x0 0 False None
255 0 0x0 0 False None
256 0 0x0 0 False None
257 0 0x0 0 False None
258 0 0x0 0 False None
259 0 0x0 0 False None
260 0 0x0 0 False None
261 0 0x0 0 False None
262 0 0x0 0 False None
263 0 0x0 0 False None
264 0 0x0 0 False None
265 0 0x0 0 False None
266 0 0x0 0 False None
267 0 0x0 0 False None
268 0 0x0 0 False None
269 0 0x0 0 False None
270 0 0x0 0 False None
271 0 0x0 0 False None
272 0 0x0 0 False None
273 0 0x0 0 False None
274 0 0x0 0 False None
275 0 0x0 0 False None
276 0 0x0 0 False None
277 0 0x0 0 False None
278 0 0x0 0 False None
279 0 0x0 0 False None
280 0 0x0 0 False None
281 0 0x0 0 False None
282 0 0x0 0 False None
283 0 0x0 0 False None
284 0 0x0 0 False None
285 0 0x0 0 False None
286 0 0x0 0 False None
287 0 0x0 0 False None
288 0 0x0 0 False None
289 0 0x0 0 False None
290 0 0x0 0 False None
291 0 0x0 0 False None
292 0 0x0 0 False None
293 0 0x0 0 False None
294 0 0x0 0 False None
295 0 0x0 0 False None
296 0 0x0 0 False None
297 0 0x0 0 False None
298 0 0x0 0 False None
299 0 0x0 0 False None
300 0 0x0 0 False None
301 0 0x0 0 False None
302 0 0x0 0 False None
303 0 0x0 0 False None
304 0 0x0 0 False None
305 0 0x0 0 False None
306 0 0x0 0 False None
307 0 0x0 0 False None
308 0 0x0 0 False None
309 0 0x0 0 False None
310 0 0x0 0 False None
311 0 0x0 0 False None
312 0 0x0 0 False None
313 0 0x0 0 False None
314 0 0x0 0 False None
315 0 0x0 0 False None
316 0 0x0 0 False None
317 0 0x0 0 False None
318 0 0x0 0 False None
319 0 0x0 0 False None
320 0 0x0 0 False None
321 0 0x0 0 False None
322 0 0x0 0 False None
323 0 0x0 0 False None
324 0 0x0 0 False None
325 0 0x0 0 False None
326 0 0x0 0 False None
327 0 0x0 0 False None
328 0 0x0 0 False None
329 0 0x0 0 False None
330 0 0x0 0 False None
331 0 0x0 0 False None
332 0 0x0 0 False None
333 0 0x0 0 False None
334 0 0x0 0 False None
335 0 0x0 0 False None
336 0 0x0 0 False None
337 0 0x0 0 False None
338 0 0x0 0 False None
339 0 0x0 0 False None
340 0 0x0 0 False None
341 0 0x0 0 False None
342 0 0x0 0 False None
343 0 0x0 0 False None
344 0 0x0 0 False None
345 0 0x0 0 False None
346 0 0x0 0 False None
347 0 0x0 0 False None
348 0 0x0 0 False None
349 0 0x0 0 False None
350 0 0x0 0 False None
351 0 0x0 0 False None
352 0 0x0 0 False None
353 0 0x0 0 False None
354 0 0x0 0 False None
355 0 0x0 0 False None
356 0 0x0 0 False None
357 0 0x0 0 False None
358 0 0x0 0 False None
359 0 0x0 0 False None
360 0 0x0 0 False None
361 0 0x0 0 False None
362 0 0x0 0 False None
363 0 0x0 0 False None
364 0 0x0 0 False None
365 0 0x0 0 False None
366 0 0x0 0 False None
367 0 0x0 0 False None
368 0 0x0 0 False None
369 0 0x0 0 False None
370 0 0x0 0 False None
371 0 0x0 0 False None
372 0 0x0 0 False None
373 0 0x0 0 False None
374 0 0x0 0 False None
375 0 0x0 0 False None
376 0 0x0 0 False None
377 0 0x0 0 False None
378 0 0x0 0 False None
379 0 0x0 0 False None
380 0 0x0 0 False None
381 0 0x0 0 False None
382 0 0x0 0 False None
383 0 0x0 0 False None
384 0 0x0 0 False None
385 0 0x0 0 False None
386 0 0x0 0 False None
387 0 0x0 0 False None
388 0 0x0 0 False None
389 0 0x0 0 False None
390 0 0x0 0 False None
391 0 0x0 0 False None
392 0 0x0 0 False None
393 0 0x0 0 False None
394 0 0x0 0 False None
395 0 0x0 0 False None
396 0 0x0 0 False None
397 0 0x0 0 False None
398 0 0x0 0 False None
399 0 0x0 0 False None
400 0 0x0 0 False None
401 0 0x0 0 False None
402 0 0x0 0 False None
403 0 0x0 0 False None
404 0 0x0 0 False None
405 0 0x0 0 False None
406 0 0x0 0 False None
407 0 0x0 0 False None
408 0 0x0 0 False None
409 0 0x0 0 False None
410 0 0x0 0 False None
411 0 0x0 0 False None
412 0 0x0 0 False None
413 0 0x0 0 False None
414 0 0x0 0 False None
415 0 0x0 0 False None
416 0 0x0 0 False None
417 0 0x0 0 False None
418 0 0x0 0 False None
419 0 0x0 0 False None
420 0 0x0 0 False None
421 0 0x0 0 False None
422 0 0x0 0 False None
423 0 0x0 0 False None
424 0 0x0 0 False None
425 0 0x0 0 False None
426 0 0x0 0 False None
427 0 0x0 0 False None
428 0 0x0 0 False None
429 0 0x0 0 False None
430 0 0x0 0 False None
431 0 0x0 0 False None
432 0 0x0 0 False None
433 0 0x0 0 False None
434 0 0x0 0 False None
435 0 0x0 0 False None
436 0 0x0 0 False None
437 0 0x0 0 False None
438 0 0x0 0 False None
439 0 0x0 0 False None
440 0 0x0 0 False None
441 0 0x0 0 False None
442 0 0x0 0 False None
443 0 0x0 0 False None
444 0 0x0 0 False None
445 0 0x0 0 False None
446 0 0x0 0 False None
447 0 0x0 0 False None
448 0 0x0 0 False None
449 0 0x0 0 False None
450 0 0x0 0 False None
451 0 0x0 0 False None
452 0 0x0 0 False None
453 0 0x0 0 False None
454 0 0x0 0 False None
455 0 0x0 0 False None
456 0 0x0 0 False None
457 0 0x0 0 False None
458 0 0x0 0 False None
459 0 0x0 0 False None
460 0 0x0 0 False None
461 0 0x0 0 False None
462 0 0x0 0 False None
463 0 0x0 0 False None
464 0 0x0 0 False None
465 0 0x0 0 False None
466 0 0x0 0 False None
467 0 0x0 0 False None
468 0 0x0 0 False None
469 0 0x0 0 False None
470 0 0x0 0 False None
471 0 0x0 0 False None
472 0 0x0 0 False None
473 0 0x0 0 False None
474 0 0x0 0 False None
475 0 0x0 0 False None
476 0 0x0 0 False None
477 0 0x0 0 False None
478 0 0x0 0 False None
479 0 0x0 0 False None
480 0 0x0 0 False None
481 0 0x0 0 False None
482 0 0x0 0 False None
483 0 0x0 0 False None
484 0 0x0 0 False None
485 0 0x0 0 False None
486 0 0x0 0 False None
487 0 0x0 0 False None
488 0 0x0 0 False None
489 0 0x0 0 False None
490 0 0x0 0 False None
491 0 0x0 0 False None
492 0 0x0 0 False None
493 0 0x0 0 False None
494 0 0x0 0 False None
495 0 0x0 0 False None
496 0 0x0 0 False None
497 0 0x0 0 False None
498 0 0x0 0 False None
499 0 0x0 0 False None
500 0 0x0 0 False None
501 0 0x0 0 False None
502 0 0x0 0 False None
503 0 0x0 0 False None
504 0 0x0 0 False None
505 0 0x0 0 False None
506 0 0x0 0 False None
507 0 0x0 0 False None
508 0 0x0 0 False None
509 0 0x0 0 False None
510 0 0x0 0 False None
511 0 0x0 0 False None
512 0 0x0 0 False None
513 0 0x0 0 False None
514 0 0x0 0 False None
515 0 0x0 0 False None
516 0 0x0 0 False None
517 0 0x0 0 False None
518 0 0x0 0 False None
519 0 0x0 0 False None
520 0 0x0 0 False None
521 0 0x0 0 False None
522 0 0x0 0 False None
523 0 0x0 0 False None
524 0 0x0 0 False None
525 0 0x0 0 False None
526 0 0x0 0 False None
527 0 0x0 0 False None
528 0 0x0 0 False None
529 0 0x0 0 False None
530 0 0x0 0 False None
531 0 0x0 0 False None
532 0 0x0 0 False None
533 0 0x0 0 False None
534 0 0x0 0 False None
535 0 0x0 0 False None
536 0 0x0 0 False None
537 0 0x0 0 False None
538 0 0x0 0 False None
539 0 0x0 0 False None
540 0 0x0 0 False None
541 0 0x0 0 False None
542 0 0x0 0 False None
543 0 0x0 0 False None
544 0 0x0 0 False None
545 0 0x0 0 False None
546 0 0x0 0 False None
547 0 0x0 0 False None
548 0 0x0 0 False None
549 0 0x0 0 False None
550 0 0x0 0 False None
551 0 0x0 0 False None
552 0 0x0 0 False None
553 0 0x0 0 False None
554 0 0x0 0 False None
555 0 0x0 0 False None
556 0 0x0 0 False None
557 0 0x0 0 False None
558 0 0x0 0 False None
559 0 0x0 0 False None
560 0 0x0 0 False None
561 0 0x0 0 False None
562 0 0x0 0 False None
563 0 0x0 0 False None
564 0 0x0 0 False None
565 0 0x0 0 False None
566 0 0x0 0 False None
567 0 0x0 0 False None
568 0 0x0 0 False None
569 0 0x0 0 False None
570 0 0x0 0 False None
571 0 0x0 0 False None
572 0 0x0 0 False None
573 0 0x0 0 False None
574 0 0x0 0 False None
575 0 0x0 0 False None
576 0 0x0 0 False None
577 0 0x0 0 False None
578 0 0x0 0 False None
579 0 0x0 0 False None
580 0 0x0 0 False None
581 0 0x0 0 False None
582 0 0x0 0 False None
583 0 0x0 0 False None
584 0 0x0 0 False None
585 0 0x0 0 False None
586 0 0x0 0 False None
587 0 0x0 0 False None
588 0 0x0 0 False None
589 0 0x0 0 False None
590 0 0x0 0 False None
591 0 0x0 0 False None
592 0 0x0 0 False None
593 0 0x0 0 False None
594 0 0x0 0 False None
595 0 0x0 0 False None
596 0 0x0 0 False None
597 0 0x0 0 False None
598 0 0x0 0 False None
599 0 0x0 0 False None
600 0 0x0 0 False None
601 0 0x0 0 False None
602 0 0x0 0 False None
603 0 0x0 0 False None
604 0 0x0 0 False None
605 0 0x0 0 False None
606 0 0x0 0 False None
607 0 0x0 0 False None
608 0 0x0 0 False None
609 0 0x0 0 False None
610 0 0x0 0 False None
611 0 0x0 0 False None
612 0 0x0 0 False None
613 0 0x0 0 False None
614 0 0x0 0 False None
615 0 0x0 0 False None
616 0 0x0 0 False None
617 0 0x0 0 False None
618 0 0x0 0 False None
619 0 0x0 0 False None
620 0 0x0 0 False None
621 0 0x0 0 False None
622 0 0x0 0 False None
623 0 0x0 0 False None
624 0 0x0 0 False None
625 0 0x0 0 False None
626 0 0x0 0 False None
627 0 0x0 0 False None
628 0 0x0 0 False None
629 0 0x0 0 False None
630 0 0x0 0 False None
631 0 0x0 0 False None
632 0 0x0 0 False None
633 0 0x0 0 False None
634 0 0x0 0 False None
635 0 0x0 0 False None
636 0 0x0 0 False None
637 0 0x0 0 False None
638 0 0x0 0 False None
639 0 0x0 0 False None
640 0 0x0 0 False None
641 0 0x0 0 False None
642 0 0x0 0 False None
643 0 0x0 0 False None
644 0 0x0 0 False None
645 0 0x0 0 False None
646 0 0x0 0 False None
647 0 0x0 0 False None
648 0 0x0 0 False None
649 0 0x0 0 False None
650 0 0x0 0 False None
651 0 0x0 0 False None
652 0 0x0 0 False None
653 0 0x0 0 False None
654 0 0x0 0 False None
655 0 0x0 0 False None
656 0 0x0 0 False None
657 0 0x0 0 False None
658 0 0x0 0 False None
659 0 0x0 0 False None
660 0 0x0 0 False None
661 0 0x0 0 False None
662 0 0x0 0 False None
663 0 0x0 0 False None
664 0 0x0 0 False None
665 0 0x0 0 False None
666 0 0x0 0 False None
667 0 0x0 0 False None
668 0 0x0 0 False None
669 0 0x0 0 False None
670 0 0x0 0 False None
671 0 0x0 0 False None
672 0 0x0 0 False None
673 0 0x0 0 False None
674 0 0x0 0 False None
675 0 0x0 0 False None
676 0 0x0 0 False None
677 0 0x0 0 False None
678 0 0x0 0 False None
679 0 0x0 0 False None
680 0 0x0 0 False None
681 0 0x0 0 False None
682 0 0x0 0 False None
683 0 0x0 0 False None
684 0 0x0 0 False None
685 0 0x0 0 False None
686 0 0x0 0 False None
687 0 0x0 0 False None
688 0 0x0 0 False None
689 0 0x0 0 False None
690 0 0x0 0 False None
691 0 0x0 0 False None
692 0 0x0 0 False None
693 0 0x0 0 False None
694 0 0x0 0 False None
695 0 0x0 0 False None
696 0 0x0 0 False None
697 0 0x0 0 False None
698 0 0x0 0 False None
699 0 0x0 0 False None
700 0 0x0 0 False None
701 0 0x0 0 False None
702 0 0x0 0 False None
703 0 0x0 0 False None
704 0 0x0 0 False None
705 0 0x0 0 False None
706 0 0x0 0 False None
707 0 0x0 0 False None
708 0 0x0 0 False None
709 0 0x0 0 False None
710 0 0x0 0 False None
711 0 0x0 0 False None
712 0 0x0 0 False None
713 0 0x0 0 False None
714 0 0x0 0 False None
715 0 0x0 0 False None
716 0 0x0 0 False None
717 0 0x0 0 False None
718 0 0x0 0 False None
719 0 0x0 0 False None
720 0 0x0 0 False None
721 0 0x0 0 False None
722 0 0x0 0 False None
723 0 0x0 0 False None
724 0 0x0 0 False None
725 0 0x0 0 False None
726 0 0x0 0 False None
727 0 0x0 0 False None
728 0 0x0 0 False None
729 0 0x0 0 False None
730 0 0x0 0 False None
731 0 0x0 0 False None
732 0 0x0 0 False None
733 0 0x0 0 False None
734 0 0x0 0 False None
735 0 0x0 0 False None
736 0 0x0 0 False None
737 0 0x0 0 False None
738 0 0x0 0 False None
739 0 0x0 0 False None
740 0 0x0 0 False None
741 0 0x0 0 False None
742 0 0x0 0 False None
743 0 0x0 0 False None
744 0 0x0 0 False None
745 0 0x0 0 False None
746 0 0x0 0 False None
747 0 0x0 0 False None
748 0 0x0 0 False None
749 0 0x0 0 False None
750 0 0x0 0 False None
751 0 0x0 0 False None
752 0 0x0 0 False None
753 0 0x0 0 False None
754 0 0x0 0 False None
755 0 0x0 0 False None
756 0 0x0 0 False None
757 0 0x0 0 False None
758 0 0x0 0 False None
759 0 0x0 0 False None
760 0 0x0 0 False None
761 0 0x0 0 False None
762 0 0x0 0 False None
763 0 0x0 0 False None
764 0 0x0 0 False None
765 0 0x0 0 False None
766 0 0x0 0 False None
767 0 0x0 0 False None
768 0 0x0 0 False None
769 0 0x0 0 False None
770 0 0x0 0 False None
771 0 0x0 0 False None
772 0 0x0 0 False None
773 0 0x0 0 False None
774 0 0x0 0 False None
775 0 0x0 0 False None
776 0 0x0 0 False None
777 0 0x0 0 False None
778 0 0x0 0 False None
779 0 0x0 0 False None
780 0 0x0 0 False None
781 0 0x0 0 False None
782 0 0x0 0 False None
783 0 0x0 0 False None
784 0 0x0 0 False None
785 0 0x0 0 False None
786 0 0x0 0 False None
787 0 0x0 0 False None
788 0 0x0 0 False None
789 0 0x0 0 False None
790 0 0x0 0 False None
791 0 0x0 0 False None
792 0 0x0 0 False None
793 0 0x0 0 False None
794 0 0x0 0 False None
795 0 0x0 0 False None
796 0 0x0 0 False None
797 0 0x0 0 False None
798 0 0x0 0 False None
799 0 0x0 0 False None
800 0 0x0 0 False None
801 0 0x0 0 False None
802 0 0x0 0 False None
803 0 0x0 0 False None
804 0 0x0 0 False None
805 0 0x0 0 False None
806 0 0x0 0 False None
807 0 0x0 0 False None
808 0 0x0 0 False None
809 0 0x0 0 False None
810 0 0x0 0 False None
811 0 0x0 0 False None
812 0 0x0 0 False None
813 0 0x0 0 False None
814 0 0x0 0 False None
815 0 0x0 0 False None
816 0 0x0 0 False None
817 0 0x0 0 False None
818 0 0x0 0 False None
819 0 0x0 0 False None
820 0 0x0 0 False None
821 0 0x0 0 False None
822 0 0x0 0 False None
823 0 0x0 0 False None
824 0 0x0 0 False None
825 0 0x0 0 False None
826 0 0x0 0 False None
827 0 0x0 0 False None
828 0 0x0 0 False None
829 0 0x0 0 False None
830 0 0x0 0 False None
831 0 0x0 0 False None
832 0 0x0 0 False None
833 0 0x0 0 False None
834 0 0x0 0 False None
835 0 0x0 0 False None
836 0 0x0 0 False None
837 0 0x0 0 False None
838 0 0x0 0 False None
839 0 0x0 0 False None
840 0 0x0 0 False None
841 0 0x0 0 False None
842 0 0x0 0 False None
843 0 0x0 0 False None
844 0 0x0 0 False None
845 0 0x0 0 False None
846 0 0x0 0 False None
847 0 0x0 0 False None
848 0 0x0 0 False None
849 0 0x0 0 False None
850 0 0x0 0 False None
851 0 0x0 0 False None
852 0 0x0 0 False None
853 0 0x0 0 False None
854 0 0x0 0 False None
855 0 0x0 0 False None
856 0 0x0 0 False None
857 0 0x0 0 False None
858 0 0x0 0 False None
859 0 0x0 0 False None
860 0 0x0 0 False None
861 0 0x0 0 False None
862 0 0x0 0 False None
863 0 0x0 0 False None
864 0 0x0 0 False None
865 0 0x0 0 False None
866 0 0x0 0 False None
867 0 0x0 0 False None
868 0 0x0 0 False None
869 0 0x0 0 False None
870 0 0x0 0 False None
871 0 0x0 0 False None
872 0 0x0 0 False None
873 0 0x0 0 False None
874 0 0x0 0 False None
875 0 0x0 0 False None
876 0 0x0 0 False None
877 0 0x0 0 False None
878 0 0x0 0 False None
879 0 0x0 0 False None
880 0 0x0 0 False None
881 0 0x0 0 False None
882 0 0x0 0 False None
883 0 0x0 0 False None
884 0 0x0 0 False None
885 0 0x0 0 False None
886 0 0x0 0 False None
887 0 0x0 0 False None
888 0 0x0 0 False None
889 0 0x0 0 False None
890 0 0x0 0 False None
891 0 0x0 0 False None
892 0 0x0 0 False None
893 0 0x0 0 False None
894 0 0x0 0 False None
895 0 0x0 0 False None
896 0 0x0 0 False None
897 0 0x0 0 False None
898 0 0x0 0 False None
899 0 0x0 0 False None
900 0 0x0 0 False None
901 0 0x0 0 False None
902 0 0x0 0 False None
903 0 0x0 0 False None
904 0 0x0 0 False None
905 0 0x0 0 False None
906 0 0x0 0 False None
907 0 0x0 0 False None
908 0 0x0 0 False None
909 0 0x0 0 False None
910 0 0x0 0 False None
911 0 0x0 0 False None
912 0 0x0 0 False None
913 0 0x0 0 False None
914 0 0x0 0 False None
915 0 0x0 0 False None
916 0 0x0 0 False None
917 0 0x0 0 False None
918 0 0x0 0 False None
919 0 0x0 0 False None
920 0 0x0 0 False None
921 0 0x0 0 False None
922 0 0x0 0 False None
-22
View File
@@ -1,22 +0,0 @@
{
"COBRAI": "1100",
"COBRATI": "1100",
"TVI": "1100",
"TRTI": "1100",
"1400": "1400",
"1500": "1500",
"1650": "1650",
"2000": "2000",
"1700": "1700",
"2100": "2100",
"2700": "2700",
"3100": "3100",
"1510": "1510",
"2200": "2200",
"3200": "3200",
"3300": "3300",
"3302": "3302",
"3303": "3303",
"3310": "3310",
"2400": "2400"
}
File diff suppressed because it is too large Load Diff
-998
View File
@@ -1,998 +0,0 @@
,,,,,,Base,Sub-type,,Accessory,,Materials,,Colors,,,,,,
DISCONT,LOC_CODE,PROD_CODE,CATEGORY,CATEGORY_NEW,DESCRIPTION,Type,Door,Window,Yes,This Item,Aluminum,Vinyl,Black,White,Bronze,Tan,Mill,Sandstone,~
FALSE,Iola,1650-10,FPPW,,#1650-10 INSULATED FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,303,STORMS,,#303 DART STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,350,STORMS,,#350 ARROW STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,404,STORMS,,#404 FALCON STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,450,STORMS,,#450 RAVEN STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,606,STORMS,,#606 LION STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,650,STORMS,,#650 LYNX STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,808,STORMS,,808 HAWK STORM WINDOW,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,850,STORMS,,#850 KENT STORM WINDOWS,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1400,SHPW,,SERIES 1400 VINYL SLIDING PRIMARY,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1500,SHPT,,SERIES 1500 S.H. TILT VINYL PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1510,FPPW,,1510 VINYL INSULATED FIXED LITE,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1650,SHPW,,#1650 INSULATED SINGLE HUNG,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700,SHPW,,#1700 INSULATED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1710,FPPW,,C-1710 FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,2000,SHPT,,SERIES 2000 S.H. T.B. TILT PRIMARY,Window,,Primary Window,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,2100,SHPT,,SERIES 2100 THERMAL BREAK SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,2200,FPPW,,SERIES 2200 T.B. FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,2400,PD,,2400 ROYAL CROWN PATIO DOOR,Door,Patio Door,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,2650,SHPW,,#2650 SINGLE HUNG SINGLE GLAZED PRIME,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2700,SHPW,,#2700 SINGLE GLAZED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2710,FPPW,,C-2710 FIXED LITE - SINGLE GLAZED,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,3000,3000DHP,#N/A,SERIES 3000 D.H. T.B REPLACEMENT WD,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3100,3000DHP,#N/A,SERIES 3100 T.B. REPLACEMENT SLIDER,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3200,3000FPP,#N/A,SERIES 3200 T.B. PICTURE WINDOW,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3300,CASEMNT,,3300 1-PANEL T.B. CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3302,CASEMNT,,3300 2-PANEL T.B. CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3303,CASEMNT,,3300 3-PANEL T.B. CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3310,CASEMNT,,3310 FIXED CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,3400,CASEMNT,,3400 1 PANEL VINYL CLAD CASEMENT,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,3402,CASEMNT,,3400 2 PANEL VINYL CLAD CASEMENT,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,3403,CASEMNT,,3400 3 PANEL VINYL CLAD CASEMENT,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,3500,CASEMNT,,3500 1-PANEL WOOD INTERIOR CASEMENT,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,3502,CASEMNT,,3500 2-PANEL WOOD INTERIOR CASEMENT,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,3503,CASEMNT,,3503 3-PANEL WOOD INTERIOR CASEMENT,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,3700,SHPW,,#3700 INSULATED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3710,FPPW,,C-3710 INSULATED FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,4100,REPLACE,,SERIES 4100 VINYL SLIDER,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,4700,SHPW,,#4700 SINGLE GLAZED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,4710,FPPW,,#4710 SINGLE GLAZED FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,5200,PD,,5200 VINYL PATIO DOORS,Door,Patio Door,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,
FALSE,Iola,5700,SHPW,,#5700 INSULATED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,6300,SHPT,,SERIES 6300 S.H. TILT VINYL PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,6301,SHPW,,SERIES 6301 VINYL SLIDING PRIMARY,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,6700,SHPW,,#6700 SINGLE GLAZED SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,265010,FPPW,,#2650-10 SINGLE GLAZED FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1400SCR,SHPW,,1400 SCREEN,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,1650SCR,SCREENS,,SCREENS FOR #1650,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1650VS,SHPW,,1650 BOTTOM SASH,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700CSC,SCREENS,,SCREEN FOR #1700 CENTER VENT SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700CV,SHPW,,1700 CENTER VENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700ESC,SCREENS,,SCREEN FOR #1700 ENDS VENT SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700EV,SHPW,,1700 END VENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700SCR,SCREENS,,SCREEN FOR #1700 SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,1700VS,SHPW,,#1700 VENT SASH,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2000SCR,SHPT,,C-2000 SCREEN,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,2100EV,2000SLI,#N/A,SERIES 2100 3-PANEL SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,2200PDG,FPPW,,SERIES 2200 TB FIXED LITE W/TEMP GLASS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,2650SCR,SCREENS,,SCREENS FOR 2650,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2650VP,SHPW,,#2650 VENT PANEL - SINGLE HUNGE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2700CV,SHPW,,C-2700 - CENTER VENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2700EV,SHPW,,C-2700 - END VENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2700SCR,SCREENS,,SCREENS FOR #2700,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,2700VS,SHPW,,#2700 VENT SASH,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,3000SCR,SCREENS,,SCREENS FOR #3000,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,305INS,INSERTS,,#305 SASH WINDCHECK INSERTS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,306INS,INSERTS,,#306 SCHLEGEL GLASS INSERTS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,3100EV,3000DHP,#N/A,SERIES 3100 3-PANEL SLIDER,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3100SCR,SCREENS,,SCREENS FOR #3100,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,310PSCR,SCRINS,,#310 PLAIN SCREENS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,3700SCR,SCREENS,,SCREEN FOR #3700 POLE BARN WD,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,3700VP,SHPW,,#3700 VENT PANEL,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,404ONE,STPW,,#404 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,450ONE,STPW,,#450 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,4700SCR,SCREENS,,SCREENS FOR #4700,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,5000SCR,SCREENS,,SCREEN FOR R5000 SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,606ONE,STPW,,#606 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,6100I,STD,,STAR 6100 FULL VIEW STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,6100L,STD,,STAR 6100 FULL VIEW STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,650ONE,STPW,,#650 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
TRUE,Iola,7100I,STD,,STAR 7100 FULL VIEW SELF STORING DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,7100L,STD,,STAR 7100 FULL VIEW SELF STORING DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,808ONE,STPW,,#808 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,8100I,STD,,STAR 8100 FULL VIEW STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,8100L,STD,,STAR 8100 FULL VIEW STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,850ONE,STPW,,#850 ONE-LITE ST WD,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,BELMONT,3000FPP,#N/A,BELMONT ALLIANCE DOUBLE HUNG WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,
FALSE,Iola,BGI,INSERTS,,BOTTOM GL INSERTS FOR ECONOMY ST WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,BGI404,INSERTS,,BOTTOM GL INSERTS FOR #404/450 ST WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,BGI606,INSERTS,,BOTTOM GL INSERTS FOR #606/650 ST WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,BGIST,INSERTS,,INSERTS FOR STORM DOORS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,C-500,SHPW,,C-500 SH THERMAL BREAK INS.,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,C1150,CASEMNT,,C1150-VINYL AWNING WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C1500AR,CIR TOP,,C-1510 VINYL ARCH TOP-OPERATING WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C1510AR,CIR TOP,,C-1510 VINYL ARCH TOP WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C1521,CIR TOP,,C-1521 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C1526,CIR TOP,,C-1526 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1621,CIR TOP,,C-1621 INSULATED CIRCLE TOP,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1622,CIR TOP,,C-1622 INSULATED CIRCLE TOP,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1626VA,CIR TOP,,C-1626VA INSULATED CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1710,SHPW,,#1710 PICTURE OVER SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,C1721,CIR TOP,,C-1721 INSULATED CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1722,CIR TOP,,C-1722 INSULATED CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1724,CIR TOP,,C-1724 INSULATED CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C1800,C1800,#N/A,C-1800 INSIDE SLIDING STORM WINDOW,Window,,Storm Window,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C2021,CIR TOP,,C-2021 T.B CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C2022,CIR TOP,,C-2022 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C2026,CIR TOP,,C-2026 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C2710,SHPW,,#2710 PICTURE OVER SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,C300,BSMT,#N/A,C-300 ALUM INSERTS FOR BASEMENT BUCKS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C3221,CIR TOP,,C-3221 T.B CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C3222,CIR TOP,,C-3222 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C3223,CIR TOP,,C-3223 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C3224,CIR TOP,,C-3224 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C3300,CASEMNT,,3300 1-PANEL T.B. CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C3700,SHPW,,C-3700 INSULATED SLIDING POLE BARN WND,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C400,BSMT,#N/A,C-400 VINYL INSERT FOR BASEMENT BUCKS,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C4000,REPLACE,,C-4000 SINGLE HUNGE PRIMARY WINDOW,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C4260,PD,,C-4260 STEEL MIRROR DOOR,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C500,SHPW,,C-500 INS THERMAL BREAK SINGLE HUNG,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,C500GL,VENTS,,LITES OF INSULATED GLASS FOR C-500'S,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C500GLP,VENTS,,LITES OF INSULATED GLASS FOR C-500'S,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C500PP,SHPW,,C-500 INS THERMAL BREAK SINGLE HUNG,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,C500SCR,SCREENS,,C-500 SCREEN,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,C500VP,VENTS,,VENT PANELS FOR C-500,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,C521,CIR TOP,,C-521 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C522,CIR TOP,,C-522 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C526,CIR TOP,,C-526 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
TRUE,Iola,C610,CASEMNT,,C610 VINYL CASEMENT WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C620,FPPW,,C620 VINYL AWNING WINDOWS,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C621,CIR TOP,,C-621 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C626,CIR TOP,,C-626 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C640,FPPW,,C-640 VINYL FIXED CASEMENT WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C826,CIR TOP,,C-826 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C828,CIR TOP,,C-828 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C8321,CIR TOP,,C-8321 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,C8326,CIR TOP,,C-8326 VINYL CIRCLE TOP,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C900,SHPW,,C-900 INS THERMAL BREAK SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C900EV,SHPW,,C-900 ENDS VENT SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C900SCR,SCREENS,,SCREEN FOR C-900,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C910,FPPW,,C-910 INSULATED T.B. FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C910PP,FPPW,,C-910 ARCH TOP,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,C921,CIR TOP,,C-921 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C922,CIR TOP,,C-922 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C924,CIR TOP,,C-924 T.B. CIRCLE TOPS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C931,CIR TOP,,C-931 T.B. ROUND PRIMARY WINDOW,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C939,CIR TOP,,C-939 T.B. ROUND PRIMARY WINDOW,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C940,CIR TOP,,C-940 T.B. OCTAGON PRIMARY,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C949,CIR TOP,,C949 OCTAGON THERMAL BREAK WINDOW,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,C960,FPPW,,C-960 INSULATED T.B. CIRCLE TOP,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,COBRAI,STD,,COLUMBIA COBRA STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,COBRAL,STD,,COLUMBIA COBRA STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,COBRATI,STD,,COLUMBIA COBRA STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,COBRATL,STD,,COLUMBIA COBRA STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,CRWNFVI,STD,,CROWN FULL VIEW STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,CRWNFVL,STD,,CROWN FULL VIEW STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,CRWNSDI,STD,,COLUMBIA CROWN SCREEN DOOR,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,CRWNSDL,STD,,COLUMBIA CROWN SCREEN DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,D770,SHPT,,D770 D.H. TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,D780,SHPW,,D780 DOUBLE SLIDE VINYL PRIMARY,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,D830,SHPT,,D830 D.H.TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,D830SCR,SHPT,,D830 SCREEN,Window,,Primary Window,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,D832,FPPW,,D832 FIXED VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,DSGLASS,GLASS,,DOUBLE STRENGTH GLASS,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,DURASEA,FPPW,,"DURASEAL 5/8"" (GRAY) PER REEL",,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,EXPAND,EXPANDR,,SILL EXPANDERS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,FULLSCR,SCREENS,,FULL SCREEN,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,FV10I,STD,,KING FV-10 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,FV10L,STD,,KING FV-10 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,FV3I,STD,,KING FV-3 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,FV3L,STD,,KING FV-3 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,FVGI,INSERTS,,GLASS INSERTS FOR KING ONE LITE,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,FVSI,INSERTS,,FULL SCREENS ONLY FOR KING ONE-LITES,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,G3000,GARDEN,,COLUMBIA COMFORT 3000 VINYL GARDEN WD,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,GOLIATH,STD,,GOLIATH STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,HERCULE,STD,,HERCULES STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,IMPERIL,PD,,IMPERIAL PATIO DOORS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,INSGLAS,GLASS,,INSULATED GLASS,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,ISP,PD,,STATIONARY PANELS FOR IMPERIAL DOORS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,IVP,PD,,VENT PANELS FOR IMPERIAL PATIO DOORS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,JET,PD,,COLUMBIA JET PATIO DOORS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,JSP,PD,,STATIONARY PANELS FOR JET DOORS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,JVP,PD,,VENT PANELS FOR JET PATIO DOORS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,KINGDVI,STD,,KING DUAL VENT STORM DOORS,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,KINGDVL,STD,,KING DUAL VENT STORM DOORS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,KINGFSC,INSERTS,,FULL SCREEN FOR KING ONE-LITE,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,KINGI,STD,,KING ONE-LITE STORM DOORS,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,KINGL,STD,,KING ONE-LITE STORM DOORS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,KINGSDI,STD,,KING ONE-LITE SCREEN DOOR ONLY,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,KINGSDL,STD,,KING ONE-LITE SCREEN DOOR ONLY,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,LINCOLN,3000DHP,#N/A,LINCOLN PRIMARY WOOD WINDOWS,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,LINCPDR,PD,,LINCOLN FRENCH PATIO DOOR,Door,Patio Door,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,M1200,PD,,M1200 PATIO STORM DOOR,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,M306,INSERTS,,M-306 SCHLEGEL GLASS INSERTS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,OUTSIDE,STDMISC,,OUTSIDE DOOR SWEEPS - ALUM + VINYL,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,PATIOSC,SCREENS,,PATIO DOOR SCREENS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,PDSCRTT,SCREENS,,SPECIAL SIZE SCREENS FOR PATIO DOORS,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,PRPDS,SCREENS,,SCREENS MADE FROM PLAIN PATIO SCR RAIL,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,PRSCR,PSCREEN,,SCREENS FOR PRIME MADE FROM #19-88,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,
FALSE,Iola,PRSCR11,PSCREEN,,SCREEN FOR PRIME MADE FROM #19-11,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,PSINS,INSERTS,,PLAIN SASH INSERTS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,PWS,STPW,,PIN-ON PICTURE WINDOWS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,
FALSE,Iola,PWSINS,INSERTS,,INSERTS ONLY FOR PIN-ON PICTURE WINDOW,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,R1150,REPLACE,,R-1150 VINYL AWNING WINDOWS,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R1400,REPLACE,,SERIES 1400 VINYL SLIDING PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R1500,REPLACE,,SERIES 1500 S.H. TILT VINYL PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R1510,FPPW,,SERIES 1510 FIXED LITE VINYL PRIMARY,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R2000,REPLACE,,SERIES 2000 S.H. T.B. TILT PRIMARY,Window,,Primary Window,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,R2100,REPLACE,,SERIES 2100 THERMAL BREAK SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,R2100EV,R2000SL,,SERIES 2100 3-PANEL T.B. SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,R2200,RFPPW,,SERIES 2200 T.B. FIXED LITE,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,R300,RBSMT,,C-300 ALUM INSERTS FOR BASEMENT BUCKS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R3302,CASEMNT,,3302 2-PANEL T.B. CASEMENT,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,R400,RBSMT,,C-400 VINYL INSERT FOR BASEMENT BUCKS,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R5000,REPLACE,,R-5000 INSULATED ALUMINUM SLIDER,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R770,REPLACE,,R770 D.H. TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,R770SCR,SCREENS,,FULL SCREEN,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R780,REPLACE,,R780 VINYL SLIDING PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R820,REPLACE,,R820 S.H. TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R821,REPLACE,,S821 SINGLE SLIDE VINYL PRIMARY,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R822,FPPW,,S822 FIXED VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R830,REPLACE,,R830 D.H.TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,R832,FPPW,,R832 FIXED VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,RCKTRAP,INSERTS,,ROCKET TRAPEZOIDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,REWIRE,SCREENS,,REWIRED SCREENS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,RNDROCK,INSERTS,,ROUND ROCKET INSERT,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,ROCKET,INSERTS,,ROCKET INSERTS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
TRUE,Iola,ROYAL,STD,,COLUMBIA ROYAL STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,RROCKET,INSERTS,,RADIUS ROCKETS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
TRUE,Iola,S820,SHPT,,S820 S.H. TILT VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,S821,SHPW,,S821 SINGLE SLIDE VINYL PRIMARY,,,,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,S822,FPPW,,S822 FIXED VINYL PRIMARY WINDOWS,Window,,Primary Window,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,SCRI,INSERTS,,SCREEN INSERTS FOR ECONOMY STORM WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,SCRI404,INSERTS,,SCREEN INSERTS FOR #404/450 STORM WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,SCRI606,INSERTS,,SCREEN INSERTS FOR #606/650 STORM WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,SCRI808,INSERTS,,SCREEN INSERTS FOR #808/850 STORM WIND,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
TRUE,Iola,SS10I,STD,,COBRA SS-10 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,SS10L,STD,,COBRA SS-10 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,SS3I,STD,,COBRA SS-3 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,SS3L,STD,,COBRA SS-3 DECORATOR STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,SSGLASS,GLASS,,SINGLE STRENGTH GLASS,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,SSSCR,INSERTS,,SCREEN INSERT FOR SELF STORING DOORS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,TBGI,INSERTS,,TEMPERED GLASS INSERTS FOR SS DOORS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,TBR,PD,,IMPERIAL T.B.R. REPLACEMENT PATIO DOOR,Door,Patio Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,TGI,INSERTS,,TOP GL INSERTS FOR ECONOMY ST WDS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,
FALSE,Iola,TGI404,INSERTS,,TOP GLASS INSERTS FOR #404/450 ST WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,TGI606,INSERTS,,TOP GLASS INSERTS FOR #606/650 ST WDS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,
FALSE,Iola,TGIODD,INSERTS,,TOP GLASS INSERTS FOR STORM DOORS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,THOR,STD,,THOR - STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,TIARAI,STD,,COLUMBIA TIARA SELF STORING STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,TIARAL,STD,,COLUMBIA TIARA SELF STORING STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
TRUE,Iola,TVGROOV,INSERTS,,TEMPERED V-GROOVE ONE-LITE INSERTS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,TVI,STD,,COLUMBIA COBRA TWIN VENT STORM DOOR,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,TVL,STD,,COLUMBIA COBRA TWIN VENT STORM DOOR,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,VKI,STOCK,,VENTILATOR KICKPANEL FOR KING ONELITE,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
TRUE,Iola,VKS,STOCK,,VENTILATOR SCREEN FOR KING ONE LITE,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,Iola,VP3700,VENTS,,VENT PANELS FOR #3700,,,,FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,
FALSE,Iola,WINDGAT,VACW,,ALLIANCE WINDGATE CASEMENT WINDOW,,,,FALSE,FALSE,FALSE,TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,FALSE,
TRUE,Iola,XBUCKIN,INSERTS,,TEMPERED GLASS INSERTS FOR CROSSBUCKS,,,,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,Iola,ZBARS,STDMISC,,Z-BARS FOR STORM DOORS,,,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,KC,COBRATK,STD,,Cobra aluminum storm door with Glass Kick Panel,Door,Storm Door,,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,~,,,,,,,,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
1 Base Sub-type Accessory Materials Colors
2 DISCONT LOC_CODE PROD_CODE CATEGORY CATEGORY_NEW DESCRIPTION Type Door Window Yes This Item Aluminum Vinyl Black White Bronze Tan Mill Sandstone ~
3 FALSE Iola 1650-10 FPPW #1650-10 INSULATED FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
4 TRUE Iola 303 STORMS #303 DART STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
5 TRUE Iola 350 STORMS #350 ARROW STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
6 FALSE Iola 404 STORMS #404 FALCON STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
7 FALSE Iola 450 STORMS #450 RAVEN STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
8 FALSE Iola 606 STORMS #606 LION STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
9 FALSE Iola 650 STORMS #650 LYNX STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
10 TRUE Iola 808 STORMS 808 HAWK STORM WINDOW Window Storm Window FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
11 TRUE Iola 850 STORMS #850 KENT STORM WINDOWS Window Storm Window FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
12 FALSE Iola 1400 SHPW SERIES 1400 VINYL SLIDING PRIMARY FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
13 FALSE Iola 1500 SHPT SERIES 1500 S.H. TILT VINYL PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
14 FALSE Iola 1510 FPPW 1510 VINYL INSULATED FIXED LITE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
15 FALSE Iola 1650 SHPW #1650 INSULATED SINGLE HUNG FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
16 FALSE Iola 1700 SHPW #1700 INSULATED SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
17 FALSE Iola 1710 FPPW C-1710 FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
18 FALSE Iola 2000 SHPT SERIES 2000 S.H. T.B. TILT PRIMARY Window Primary Window FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
19 FALSE Iola 2100 SHPT SERIES 2100 THERMAL BREAK SLIDER FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
20 FALSE Iola 2200 FPPW SERIES 2200 T.B. FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
21 TRUE Iola 2400 PD 2400 ROYAL CROWN PATIO DOOR Door Patio Door FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
22 FALSE Iola 2650 SHPW #2650 SINGLE HUNG SINGLE GLAZED PRIME FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
23 FALSE Iola 2700 SHPW #2700 SINGLE GLAZED SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
24 FALSE Iola 2710 FPPW C-2710 FIXED LITE - SINGLE GLAZED FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
25 FALSE Iola 3000 3000DHP #N/A SERIES 3000 D.H. T.B REPLACEMENT WD FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
26 FALSE Iola 3100 3000DHP #N/A SERIES 3100 T.B. REPLACEMENT SLIDER FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
27 FALSE Iola 3200 3000FPP #N/A SERIES 3200 T.B. PICTURE WINDOW FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
28 FALSE Iola 3300 CASEMNT 3300 1-PANEL T.B. CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
29 FALSE Iola 3302 CASEMNT 3300 2-PANEL T.B. CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
30 FALSE Iola 3303 CASEMNT 3300 3-PANEL T.B. CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
31 FALSE Iola 3310 CASEMNT 3310 FIXED CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
32 TRUE Iola 3400 CASEMNT 3400 1 PANEL VINYL CLAD CASEMENT FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
33 TRUE Iola 3402 CASEMNT 3400 2 PANEL VINYL CLAD CASEMENT FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
34 TRUE Iola 3403 CASEMNT 3400 3 PANEL VINYL CLAD CASEMENT FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
35 TRUE Iola 3500 CASEMNT 3500 1-PANEL WOOD INTERIOR CASEMENT FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
36 TRUE Iola 3502 CASEMNT 3500 2-PANEL WOOD INTERIOR CASEMENT FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
37 TRUE Iola 3503 CASEMNT 3503 3-PANEL WOOD INTERIOR CASEMENT FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
38 FALSE Iola 3700 SHPW #3700 INSULATED SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
39 FALSE Iola 3710 FPPW C-3710 INSULATED FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
40 TRUE Iola 4100 REPLACE SERIES 4100 VINYL SLIDER FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
41 FALSE Iola 4700 SHPW #4700 SINGLE GLAZED SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
42 FALSE Iola 4710 FPPW #4710 SINGLE GLAZED FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
43 FALSE Iola 5200 PD 5200 VINYL PATIO DOORS Door Patio Door FALSE FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE
44 FALSE Iola 5700 SHPW #5700 INSULATED SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
45 TRUE Iola 6300 SHPT SERIES 6300 S.H. TILT VINYL PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
46 TRUE Iola 6301 SHPW SERIES 6301 VINYL SLIDING PRIMARY FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
47 FALSE Iola 6700 SHPW #6700 SINGLE GLAZED SLIDER FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
48 FALSE Iola 265010 FPPW #2650-10 SINGLE GLAZED FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
49 FALSE Iola 1400SCR SHPW 1400 SCREEN FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
50 FALSE Iola 1650SCR SCREENS SCREENS FOR #1650 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
51 FALSE Iola 1650VS SHPW 1650 BOTTOM SASH FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
52 FALSE Iola 1700CSC SCREENS SCREEN FOR #1700 CENTER VENT SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
53 FALSE Iola 1700CV SHPW 1700 CENTER VENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
54 FALSE Iola 1700ESC SCREENS SCREEN FOR #1700 ENDS VENT SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
55 FALSE Iola 1700EV SHPW 1700 END VENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
56 FALSE Iola 1700SCR SCREENS SCREEN FOR #1700 SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
57 FALSE Iola 1700VS SHPW #1700 VENT SASH FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
58 FALSE Iola 2000SCR SHPT C-2000 SCREEN FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
59 FALSE Iola 2100EV 2000SLI #N/A SERIES 2100 3-PANEL SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
60 FALSE Iola 2200PDG FPPW SERIES 2200 TB FIXED LITE W/TEMP GLASS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
61 FALSE Iola 2650SCR SCREENS SCREENS FOR 2650 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
62 FALSE Iola 2650VP SHPW #2650 VENT PANEL - SINGLE HUNGE FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
63 FALSE Iola 2700CV SHPW C-2700 - CENTER VENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
64 FALSE Iola 2700EV SHPW C-2700 - END VENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
65 FALSE Iola 2700SCR SCREENS SCREENS FOR #2700 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
66 FALSE Iola 2700VS SHPW #2700 VENT SASH FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
67 FALSE Iola 3000SCR SCREENS SCREENS FOR #3000 FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
68 FALSE Iola 305INS INSERTS #305 SASH WINDCHECK INSERTS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
69 FALSE Iola 306INS INSERTS #306 SCHLEGEL GLASS INSERTS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
70 FALSE Iola 3100EV 3000DHP #N/A SERIES 3100 3-PANEL SLIDER FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
71 FALSE Iola 3100SCR SCREENS SCREENS FOR #3100 FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
72 FALSE Iola 310PSCR SCRINS #310 PLAIN SCREENS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
73 FALSE Iola 3700SCR SCREENS SCREEN FOR #3700 POLE BARN WD FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
74 FALSE Iola 3700VP SHPW #3700 VENT PANEL FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
75 FALSE Iola 404ONE STPW #404 ONE-LITE ST WD FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
76 FALSE Iola 450ONE STPW #450 ONE-LITE ST WD FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
77 FALSE Iola 4700SCR SCREENS SCREENS FOR #4700 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
78 TRUE Iola 5000SCR SCREENS SCREEN FOR R5000 SLIDER FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
79 FALSE Iola 606ONE STPW #606 ONE-LITE ST WD FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE FALSE
80 FALSE Iola 6100I STD STAR 6100 FULL VIEW STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
81 TRUE Iola 6100L STD STAR 6100 FULL VIEW STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
82 FALSE Iola 650ONE STPW #650 ONE-LITE ST WD FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
83 TRUE Iola 7100I STD STAR 7100 FULL VIEW SELF STORING DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
84 TRUE Iola 7100L STD STAR 7100 FULL VIEW SELF STORING DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
85 TRUE Iola 808ONE STPW #808 ONE-LITE ST WD FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
86 FALSE Iola 8100I STD STAR 8100 FULL VIEW STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
87 TRUE Iola 8100L STD STAR 8100 FULL VIEW STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
88 TRUE Iola 850ONE STPW #850 ONE-LITE ST WD FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
89 FALSE Iola BELMONT 3000FPP #N/A BELMONT ALLIANCE DOUBLE HUNG WINDOW FALSE FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE
90 FALSE Iola BGI INSERTS BOTTOM GL INSERTS FOR ECONOMY ST WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
91 FALSE Iola BGI404 INSERTS BOTTOM GL INSERTS FOR #404/450 ST WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
92 FALSE Iola BGI606 INSERTS BOTTOM GL INSERTS FOR #606/650 ST WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
93 FALSE Iola BGIST INSERTS INSERTS FOR STORM DOORS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
94 FALSE Iola C-500 SHPW C-500 SH THERMAL BREAK INS. FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
95 FALSE Iola C1150 CASEMNT C1150-VINYL AWNING WINDOW FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
96 TRUE Iola C1500AR CIR TOP C-1510 VINYL ARCH TOP-OPERATING WINDOW FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
97 TRUE Iola C1510AR CIR TOP C-1510 VINYL ARCH TOP WINDOW FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
98 TRUE Iola C1521 CIR TOP C-1521 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
99 TRUE Iola C1526 CIR TOP C-1526 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
100 FALSE Iola C1621 CIR TOP C-1621 INSULATED CIRCLE TOP FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
101 FALSE Iola C1622 CIR TOP C-1622 INSULATED CIRCLE TOP FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
102 FALSE Iola C1626VA CIR TOP C-1626VA INSULATED CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
103 FALSE Iola C1710 SHPW #1710 PICTURE OVER SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
104 FALSE Iola C1721 CIR TOP C-1721 INSULATED CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
105 FALSE Iola C1722 CIR TOP C-1722 INSULATED CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
106 FALSE Iola C1724 CIR TOP C-1724 INSULATED CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
107 FALSE Iola C1800 C1800 #N/A C-1800 INSIDE SLIDING STORM WINDOW Window Storm Window FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
108 FALSE Iola C2021 CIR TOP C-2021 T.B CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
109 FALSE Iola C2022 CIR TOP C-2022 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
110 FALSE Iola C2026 CIR TOP C-2026 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
111 FALSE Iola C2710 SHPW #2710 PICTURE OVER SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
112 FALSE Iola C300 BSMT #N/A C-300 ALUM INSERTS FOR BASEMENT BUCKS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
113 FALSE Iola C3221 CIR TOP C-3221 T.B CIRCLE TOPS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
114 FALSE Iola C3222 CIR TOP C-3222 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
115 FALSE Iola C3223 CIR TOP C-3223 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
116 FALSE Iola C3224 CIR TOP C-3224 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
117 FALSE Iola C3300 CASEMNT 3300 1-PANEL T.B. CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
118 FALSE Iola C3700 SHPW C-3700 INSULATED SLIDING POLE BARN WND FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
119 FALSE Iola C400 BSMT #N/A C-400 VINYL INSERT FOR BASEMENT BUCKS FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
120 TRUE Iola C4000 REPLACE C-4000 SINGLE HUNGE PRIMARY WINDOW Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
121 TRUE Iola C4260 PD C-4260 STEEL MIRROR DOOR FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
122 FALSE Iola C500 SHPW C-500 INS THERMAL BREAK SINGLE HUNG FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
123 FALSE Iola C500GL VENTS LITES OF INSULATED GLASS FOR C-500'S FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
124 FALSE Iola C500GLP VENTS LITES OF INSULATED GLASS FOR C-500'S FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
125 FALSE Iola C500PP SHPW C-500 INS THERMAL BREAK SINGLE HUNG FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
126 FALSE Iola C500SCR SCREENS C-500 SCREEN FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
127 FALSE Iola C500VP VENTS VENT PANELS FOR C-500 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
128 FALSE Iola C521 CIR TOP C-521 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
129 FALSE Iola C522 CIR TOP C-522 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
130 FALSE Iola C526 CIR TOP C-526 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
131 TRUE Iola C610 CASEMNT C610 VINYL CASEMENT WINDOW FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
132 TRUE Iola C620 FPPW C620 VINYL AWNING WINDOWS FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
133 TRUE Iola C621 CIR TOP C-621 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
134 TRUE Iola C626 CIR TOP C-626 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
135 TRUE Iola C640 FPPW C-640 VINYL FIXED CASEMENT WINDOW FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
136 TRUE Iola C826 CIR TOP C-826 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
137 TRUE Iola C828 CIR TOP C-828 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
138 TRUE Iola C8321 CIR TOP C-8321 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
139 TRUE Iola C8326 CIR TOP C-8326 VINYL CIRCLE TOP FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
140 FALSE Iola C900 SHPW C-900 INS THERMAL BREAK SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
141 FALSE Iola C900EV SHPW C-900 ENDS VENT SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
142 FALSE Iola C900SCR SCREENS SCREEN FOR C-900 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
143 FALSE Iola C910 FPPW C-910 INSULATED T.B. FIXED LITE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
144 FALSE Iola C910PP FPPW C-910 ARCH TOP FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
145 FALSE Iola C921 CIR TOP C-921 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
146 FALSE Iola C922 CIR TOP C-922 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
147 FALSE Iola C924 CIR TOP C-924 T.B. CIRCLE TOPS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
148 FALSE Iola C931 CIR TOP C-931 T.B. ROUND PRIMARY WINDOW FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
149 FALSE Iola C939 CIR TOP C-939 T.B. ROUND PRIMARY WINDOW FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
150 FALSE Iola C940 CIR TOP C-940 T.B. OCTAGON PRIMARY FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
151 FALSE Iola C949 CIR TOP C949 OCTAGON THERMAL BREAK WINDOW FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
152 FALSE Iola C960 FPPW C-960 INSULATED T.B. CIRCLE TOP FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
153 FALSE Iola COBRAI STD COLUMBIA COBRA STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
154 TRUE Iola COBRAL STD COLUMBIA COBRA STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
155 FALSE Iola COBRATI STD COLUMBIA COBRA STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
156 TRUE Iola COBRATL STD COLUMBIA COBRA STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
157 FALSE Iola CRWNFVI STD CROWN FULL VIEW STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
158 TRUE Iola CRWNFVL STD CROWN FULL VIEW STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
159 FALSE Iola CRWNSDI STD COLUMBIA CROWN SCREEN DOOR FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
160 TRUE Iola CRWNSDL STD COLUMBIA CROWN SCREEN DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
161 FALSE Iola D770 SHPT D770 D.H. TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
162 TRUE Iola D780 SHPW D780 DOUBLE SLIDE VINYL PRIMARY FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
163 TRUE Iola D830 SHPT D830 D.H.TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
164 TRUE Iola D830SCR SHPT D830 SCREEN Window Primary Window FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
165 TRUE Iola D832 FPPW D832 FIXED VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
166 FALSE Iola DSGLASS GLASS DOUBLE STRENGTH GLASS FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
167 FALSE Iola DURASEA FPPW DURASEAL 5/8" (GRAY) PER REEL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
168 FALSE Iola EXPAND EXPANDR SILL EXPANDERS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
169 FALSE Iola FULLSCR SCREENS FULL SCREEN FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
170 TRUE Iola FV10I STD KING FV-10 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
171 TRUE Iola FV10L STD KING FV-10 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
172 TRUE Iola FV3I STD KING FV-3 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
173 TRUE Iola FV3L STD KING FV-3 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
174 FALSE Iola FVGI INSERTS GLASS INSERTS FOR KING ONE LITE FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
175 FALSE Iola FVSI INSERTS FULL SCREENS ONLY FOR KING ONE-LITES FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
176 TRUE Iola G3000 GARDEN COLUMBIA COMFORT 3000 VINYL GARDEN WD FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
177 FALSE Iola GOLIATH STD GOLIATH STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
178 FALSE Iola HERCULE STD HERCULES STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
179 FALSE Iola IMPERIL PD IMPERIAL PATIO DOORS Door Patio Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
180 FALSE Iola INSGLAS GLASS INSULATED GLASS FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
181 FALSE Iola ISP PD STATIONARY PANELS FOR IMPERIAL DOORS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
182 FALSE Iola IVP PD VENT PANELS FOR IMPERIAL PATIO DOORS Door Patio Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
183 FALSE Iola JET PD COLUMBIA JET PATIO DOORS Door Patio Door FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
184 FALSE Iola JSP PD STATIONARY PANELS FOR JET DOORS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
185 FALSE Iola JVP PD VENT PANELS FOR JET PATIO DOORS Door Patio Door FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
186 FALSE Iola KINGDVI STD KING DUAL VENT STORM DOORS Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
187 TRUE Iola KINGDVL STD KING DUAL VENT STORM DOORS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
188 FALSE Iola KINGFSC INSERTS FULL SCREEN FOR KING ONE-LITE FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
189 FALSE Iola KINGI STD KING ONE-LITE STORM DOORS Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
190 TRUE Iola KINGL STD KING ONE-LITE STORM DOORS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
191 FALSE Iola KINGSDI STD KING ONE-LITE SCREEN DOOR ONLY Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
192 TRUE Iola KINGSDL STD KING ONE-LITE SCREEN DOOR ONLY FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
193 TRUE Iola LINCOLN 3000DHP #N/A LINCOLN PRIMARY WOOD WINDOWS FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
194 TRUE Iola LINCPDR PD LINCOLN FRENCH PATIO DOOR Door Patio Door FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
195 FALSE Iola M1200 PD M1200 PATIO STORM DOOR Door Patio Door FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
196 FALSE Iola M306 INSERTS M-306 SCHLEGEL GLASS INSERTS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
197 FALSE Iola OUTSIDE STDMISC OUTSIDE DOOR SWEEPS - ALUM + VINYL FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
198 FALSE Iola PATIOSC SCREENS PATIO DOOR SCREENS Door Patio Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
199 FALSE Iola PDSCRTT SCREENS SPECIAL SIZE SCREENS FOR PATIO DOORS Door Patio Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
200 FALSE Iola PRPDS SCREENS SCREENS MADE FROM PLAIN PATIO SCR RAIL FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
201 FALSE Iola PRSCR PSCREEN SCREENS FOR PRIME MADE FROM #19-88 FALSE FALSE TRUE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
202 FALSE Iola PRSCR11 PSCREEN SCREEN FOR PRIME MADE FROM #19-11 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
203 FALSE Iola PSINS INSERTS PLAIN SASH INSERTS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
204 FALSE Iola PWS STPW PIN-ON PICTURE WINDOWS FALSE FALSE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE
205 FALSE Iola PWSINS INSERTS INSERTS ONLY FOR PIN-ON PICTURE WINDOW FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
206 FALSE Iola R1150 REPLACE R-1150 VINYL AWNING WINDOWS FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
207 FALSE Iola R1400 REPLACE SERIES 1400 VINYL SLIDING PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
208 FALSE Iola R1500 REPLACE SERIES 1500 S.H. TILT VINYL PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
209 FALSE Iola R1510 FPPW SERIES 1510 FIXED LITE VINYL PRIMARY FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
210 FALSE Iola R2000 REPLACE SERIES 2000 S.H. T.B. TILT PRIMARY Window Primary Window FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
211 FALSE Iola R2100 REPLACE SERIES 2100 THERMAL BREAK SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
212 FALSE Iola R2100EV R2000SL SERIES 2100 3-PANEL T.B. SLIDER FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
213 FALSE Iola R2200 RFPPW SERIES 2200 T.B. FIXED LITE FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
214 FALSE Iola R300 RBSMT C-300 ALUM INSERTS FOR BASEMENT BUCKS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
215 FALSE Iola R3302 CASEMNT 3302 2-PANEL T.B. CASEMENT FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
216 FALSE Iola R400 RBSMT C-400 VINYL INSERT FOR BASEMENT BUCKS FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
217 TRUE Iola R5000 REPLACE R-5000 INSULATED ALUMINUM SLIDER FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
218 FALSE Iola R770 REPLACE R770 D.H. TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
219 FALSE Iola R770SCR SCREENS FULL SCREEN FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
220 TRUE Iola R780 REPLACE R780 VINYL SLIDING PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
221 TRUE Iola R820 REPLACE R820 S.H. TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
222 TRUE Iola R821 REPLACE S821 SINGLE SLIDE VINYL PRIMARY Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
223 TRUE Iola R822 FPPW S822 FIXED VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
224 TRUE Iola R830 REPLACE R830 D.H.TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
225 TRUE Iola R832 FPPW R832 FIXED VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
226 FALSE Iola RCKTRAP INSERTS ROCKET TRAPEZOIDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
227 FALSE Iola REWIRE SCREENS REWIRED SCREENS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
228 FALSE Iola RNDROCK INSERTS ROUND ROCKET INSERT FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
229 FALSE Iola ROCKET INSERTS ROCKET INSERTS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
230 TRUE Iola ROYAL STD COLUMBIA ROYAL STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
231 FALSE Iola RROCKET INSERTS RADIUS ROCKETS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
232 TRUE Iola S820 SHPT S820 S.H. TILT VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
233 TRUE Iola S821 SHPW S821 SINGLE SLIDE VINYL PRIMARY FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
234 TRUE Iola S822 FPPW S822 FIXED VINYL PRIMARY WINDOWS Window Primary Window FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
235 FALSE Iola SCRI INSERTS SCREEN INSERTS FOR ECONOMY STORM WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
236 FALSE Iola SCRI404 INSERTS SCREEN INSERTS FOR #404/450 STORM WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
237 FALSE Iola SCRI606 INSERTS SCREEN INSERTS FOR #606/650 STORM WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
238 FALSE Iola SCRI808 INSERTS SCREEN INSERTS FOR #808/850 STORM WIND FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
239 TRUE Iola SS10I STD COBRA SS-10 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
240 TRUE Iola SS10L STD COBRA SS-10 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
241 TRUE Iola SS3I STD COBRA SS-3 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
242 TRUE Iola SS3L STD COBRA SS-3 DECORATOR STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
243 FALSE Iola SSGLASS GLASS SINGLE STRENGTH GLASS FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
244 FALSE Iola SSSCR INSERTS SCREEN INSERT FOR SELF STORING DOORS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
245 FALSE Iola TBGI INSERTS TEMPERED GLASS INSERTS FOR SS DOORS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
246 FALSE Iola TBR PD IMPERIAL T.B.R. REPLACEMENT PATIO DOOR Door Patio Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
247 FALSE Iola TGI INSERTS TOP GL INSERTS FOR ECONOMY ST WDS FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE TRUE FALSE
248 FALSE Iola TGI404 INSERTS TOP GLASS INSERTS FOR #404/450 ST WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
249 FALSE Iola TGI606 INSERTS TOP GLASS INSERTS FOR #606/650 ST WDS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
250 FALSE Iola TGIODD INSERTS TOP GLASS INSERTS FOR STORM DOORS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
251 FALSE Iola THOR STD THOR - STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
252 TRUE Iola TIARAI STD COLUMBIA TIARA SELF STORING STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
253 TRUE Iola TIARAL STD COLUMBIA TIARA SELF STORING STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
254 TRUE Iola TVGROOV INSERTS TEMPERED V-GROOVE ONE-LITE INSERTS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
255 FALSE Iola TVI STD COLUMBIA COBRA TWIN VENT STORM DOOR Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
256 TRUE Iola TVL STD COLUMBIA COBRA TWIN VENT STORM DOOR FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
257 FALSE Iola VKI STOCK VENTILATOR KICKPANEL FOR KING ONELITE FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
258 TRUE Iola VKS STOCK VENTILATOR SCREEN FOR KING ONE LITE FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
259 FALSE Iola VP3700 VENTS VENT PANELS FOR #3700 FALSE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
260 FALSE Iola WINDGAT VACW ALLIANCE WINDGATE CASEMENT WINDOW FALSE FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE
261 TRUE Iola XBUCKIN INSERTS TEMPERED GLASS INSERTS FOR CROSSBUCKS FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
262 FALSE Iola ZBARS STDMISC Z-BARS FOR STORM DOORS FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
263 FALSE KC COBRATK STD Cobra aluminum storm door with Glass Kick Panel Door Storm Door FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
264 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
265 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
266 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
267 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
268 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
269 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
270 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
271 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
272 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
273 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
274 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
275 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
276 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
277 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
278 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
279 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
280 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
281 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
282 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
283 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
284 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
285 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
286 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
287 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
288 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
289 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
290 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
291 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
292 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
293 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
294 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
295 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
296 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
297 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
298 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
299 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
300 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
301 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
302 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
303 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
304 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
305 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
306 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
307 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
308 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
309 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
310 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
311 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
312 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
313 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
314 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
315 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
316 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
317 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
318 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
319 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
320 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
321 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
322 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
323 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
324 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
325 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
326 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
327 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
328 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
329 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
330 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
331 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
332 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
333 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
334 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
335 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
336 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
337 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
338 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
339 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
340 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
341 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
342 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
343 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
344 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
345 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
346 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
347 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
348 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
349 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
350 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
351 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
352 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
353 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
354 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
355 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
356 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
357 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
358 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
359 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
360 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
361 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
362 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
363 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
364 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
365 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
366 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
367 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
368 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
369 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
370 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
371 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
372 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
373 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
374 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
375 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
376 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
377 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
378 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
379 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
380 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
381 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
382 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
383 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
384 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
385 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
386 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
387 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
388 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
389 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
390 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
391 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
392 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
393 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
394 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
395 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
396 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
397 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
398 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
399 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
400 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
401 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
402 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
403 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
404 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
405 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
406 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
407 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
408 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
409 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
410 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
411 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
412 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
413 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
414 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
415 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
416 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
417 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
418 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
419 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
420 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
421 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
422 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
423 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
424 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
425 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
426 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
427 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
428 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
429 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
430 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
431 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
432 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
433 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
434 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
435 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
436 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
437 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
438 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
439 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
440 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
441 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
442 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
443 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
444 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
445 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
446 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
447 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
448 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
449 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
450 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
451 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
452 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
453 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
454 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
455 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
456 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
457 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
458 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
459 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
460 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
461 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
462 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
463 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
464 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
465 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
466 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
467 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
468 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
469 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
470 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
471 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
472 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
473 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
474 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
475 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
476 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
477 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
478 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
479 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
480 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
481 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
482 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
483 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
484 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
485 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
486 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
487 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
488 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
489 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
490 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
491 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
492 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
493 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
494 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
495 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
496 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
497 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
498 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
499 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
500 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
501 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
502 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
503 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
504 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
505 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
506 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
507 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
508 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
509 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
510 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
511 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
512 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
513 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
514 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
515 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
516 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
517 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
518 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
519 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
520 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
521 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
522 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
523 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
524 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
525 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
526 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
527 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
528 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
529 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
530 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
531 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
532 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
533 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
534 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
535 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
536 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
537 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
538 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
539 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
540 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
541 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
542 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
543 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
544 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
545 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
546 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
547 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
548 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
549 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
550 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
551 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
552 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
553 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
554 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
555 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
556 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
557 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
558 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
559 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
560 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
561 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
562 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
563 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
564 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
565 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
566 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
567 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
568 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
569 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
570 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
571 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
572 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
573 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
574 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
575 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
576 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
577 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
578 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
579 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
580 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
581 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
582 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
583 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
584 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
585 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
586 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
587 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
588 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
589 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
590 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
591 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
592 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
593 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
594 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
595 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
596 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
597 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
598 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
599 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
600 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
601 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
602 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
603 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
604 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
605 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
606 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
607 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
608 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
609 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
610 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
611 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
612 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
613 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
614 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
615 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
616 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
617 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
618 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
619 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
620 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
621 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
622 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
623 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
624 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
625 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
626 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
627 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
628 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
629 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
630 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
631 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
632 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
633 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
634 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
635 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
636 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
637 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
638 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
639 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
640 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
641 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
642 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
643 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
644 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
645 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
646 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
647 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
648 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
649 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
650 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
651 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
652 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
653 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
654 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
655 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
656 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
657 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
658 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
659 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
660 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
661 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
662 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
663 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
664 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
665 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
666 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
667 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
668 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
669 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
670 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
671 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
672 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
673 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
674 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
675 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
676 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
677 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
678 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
679 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
680 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
681 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
682 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
683 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
684 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
685 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
686 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
687 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
688 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
689 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
690 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
691 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
692 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
693 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
694 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
695 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
696 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
697 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
698 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
699 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
700 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
701 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
702 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
703 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
704 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
705 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
706 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
707 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
708 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
709 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
710 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
711 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
712 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
713 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
714 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
715 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
716 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
717 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
718 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
719 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
720 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
721 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
722 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
723 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
724 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
725 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
726 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
727 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
728 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
729 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
730 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
731 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
732 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
733 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
734 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
735 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
736 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
737 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
738 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
739 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
740 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
741 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
742 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
743 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
744 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
745 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
746 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
747 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
748 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
749 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
750 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
751 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
752 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
753 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
754 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
755 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
756 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
757 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
758 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
759 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
760 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
761 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
762 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
763 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
764 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
765 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
766 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
767 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
768 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
769 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
770 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
771 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
772 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
773 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
774 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
775 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
776 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
777 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
778 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
779 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
780 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
781 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
782 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
783 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
784 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
785 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
786 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
787 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
788 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
789 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
790 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
791 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
792 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
793 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
794 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
795 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
796 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
797 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
798 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
799 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
800 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
801 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
802 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
803 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
804 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
805 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
806 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
807 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
808 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
809 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
810 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
811 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
812 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
813 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
814 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
815 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
816 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
817 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
818 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
819 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
820 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
821 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
822 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
823 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
824 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
825 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
826 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
827 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
828 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
829 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
830 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
831 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
832 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
833 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
834 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
835 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
836 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
837 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
838 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
839 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
840 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
841 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
842 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
843 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
844 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
845 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
846 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
847 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
848 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
849 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
850 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
851 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
852 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
853 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
854 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
855 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
856 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
857 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
858 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
859 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
860 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
861 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
862 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
863 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
864 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
865 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
866 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
867 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
868 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
869 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
870 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
871 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
872 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
873 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
874 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
875 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
876 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
877 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
878 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
879 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
880 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
881 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
882 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
883 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
884 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
885 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
886 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
887 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
888 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
889 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
890 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
891 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
892 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
893 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
894 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
895 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
896 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
897 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
898 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
899 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
900 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
901 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
902 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
903 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
904 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
905 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
906 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
907 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
908 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
909 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
910 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
911 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
912 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
913 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
914 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
915 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
916 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
917 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
918 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
919 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
920 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
921 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
922 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
923 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
924 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
925 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
926 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
927 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
928 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
929 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
930 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
931 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
932 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
933 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
934 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
935 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
936 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
937 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
938 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
939 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
940 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
941 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
942 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
943 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
944 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
945 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
946 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
947 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
948 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
949 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
950 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
951 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
952 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
953 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
954 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
955 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
956 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
957 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
958 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
959 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
960 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
961 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
962 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
963 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
964 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
965 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
966 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
967 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
968 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
969 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
970 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
971 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
972 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
973 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
974 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
975 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
976 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
977 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
978 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
979 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
980 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
981 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
982 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
983 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
984 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
985 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
986 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
987 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
988 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
989 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
990 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
991 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
992 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
993 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
994 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
995 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
996 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
997 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
998 FALSE ~ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
+18 -55
View File
@@ -4,12 +4,7 @@
"password": "pbkdf2:sha256:1000000$tPRmseRGKLveXTxS$87eda9a20db29d12838fcb607f1f3536141f743ec9879702dc2a0dd893b4078d",
"defaultLocation": "KC",
"permissions": {
"manage_users": true,
"view_reports": true,
"create_quotes": true,
"approve_quotes": true,
"manage_products": true,
"manage_inventory": true
"manage_users": true
},
"locationSettings": {
"LINDS": {
@@ -25,74 +20,42 @@
"accessible": true
}
},
"active": true
"active": true,
"superAdmin": true
},
{
"username": "Darlene",
"password": "pbkdf2:sha256:1000000$8sblSWLWIvsjcta2$d974d13956f67cc42e1fa88191d68c896d4daa663ae2d76d7988beb569647d27",
"password": "pbkdf2:sha256:1000000$TSAG3KNMWuEQr3Jl$7e8eda7495bc11a43161df75465ce06a53c29f47e766928914dfeb42388a0a5b",
"defaultLocation": "IOLA",
"permissions": {
"manage_users": false,
"view_reports": true,
"create_quotes": true,
"approve_quotes": false,
"manage_products": false,
"manage_inventory": false
},
"locationSettings": {
"LINDS": {
"accessible": true
"accessible": true,
"permissions": {}
},
"IOLA": {
"accessible": true
},
"KC": {
"accessible": true
},
"BMD": {
"accessible": false
"accessible": true,
"permissions": {}
}
},
"permissions": {
"manage_users": true,
"create_quotes": true
},
"active": true
},
{
"username": "Toni",
"password": "pbkdf2:sha256:1000000$5k3daJKZt7hqNAkq$e77819a2b2ee4bf9955dc10b3b4da7b14de2b4ecda5ce5f553daf3783b0a316c",
"password": "pbkdf2:sha256:1000000$kf8fP8xO1ghC5Fig$e3b4155b7922a651e0680e73c984a48c7d4de2b02a43254d9080498c1071baca",
"defaultLocation": "LINDS",
"locationSettings": {
"LINDS": {
"accessible": true
},
"IOLA": {
"accessible": false
},
"KC": {
"accessible": false
},
"BMD": {
"accessible": false
"accessible": true,
"permissions": {}
}
},
"permissions": {
"create_quotes": true
},
"active": true
},
{
"username": "Jason",
"password": "pbkdf2:sha256:1000000$rNSYLqRWZ6tdny1G$cad2afda9193b7cb50b9e9423f95ff83bc14428c8a2d98607cd6e5ce17cb70c7",
"defaultLocation": "KC",
"locationSettings": {
"LINDS": {
"accessible": true
},
"IOLA": {
"accessible": true
},
"KC": {
"accessible": true
},
"BMD": {
"accessible": true
}
},
"active": false
}
]
-111
View File
@@ -1,111 +0,0 @@
"""
Debug startup script - writes detailed logs to file
Upload this and temporarily set it as the startup file to diagnose issues
"""
import sys
import os
from datetime import datetime
# Create log file
log_file = '/home/bmdwtjuw/product-finder/startup_debug.log'
def log(message):
with open(log_file, 'a') as f:
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
f.write(f"[{timestamp}] {message}\n")
try:
log("="*70)
log("STARTUP DEBUG - BEGIN")
log("="*70)
# Python info
log(f"Python version: {sys.version}")
log(f"Python executable: {sys.executable}")
log(f"Current directory: {os.getcwd()}")
# Environment variables
log("\nEnvironment Variables:")
log(f" APPLICATION_ROOT: {os.environ.get('APPLICATION_ROOT', 'NOT SET')}")
log(f" FLASK_ENV: {os.environ.get('FLASK_ENV', 'NOT SET')}")
# Python path
log(f"\nPython path: {sys.path}")
# Check Flask installation
log("\nChecking Flask installation...")
try:
import flask
log(f" ✓ Flask version: {flask.__version__ if hasattr(flask, '__version__') else 'unknown'}")
except ImportError as e:
log(f" ✗ Flask NOT installed: {e}")
log(" RUN: pip install Flask==3.0.0 Werkzeug==3.0.1")
# Check Werkzeug
try:
import werkzeug
log(f" ✓ Werkzeug version: {werkzeug.__version__ if hasattr(werkzeug, '__version__') else 'unknown'}")
except ImportError as e:
log(f" ✗ Werkzeug NOT installed: {e}")
# Check if app.py exists
log("\nChecking files...")
app_py_path = os.path.join(os.path.dirname(__file__), 'app.py')
if os.path.exists(app_py_path):
log(f" ✓ app.py exists at {app_py_path}")
else:
log(f" ✗ app.py NOT FOUND at {app_py_path}")
# Try importing app
log("\nAttempting to import Flask app...")
try:
from app import app
log(f" ✓ Successfully imported Flask app")
log(f" APPLICATION_ROOT config: {app.config.get('APPLICATION_ROOT', 'NOT SET')}")
# Count routes
routes = list(app.url_map.iter_rules())
log(f" ✓ Registered routes: {len(routes)}")
# Create WSGI application
def application(environ, start_response):
log(f"\nRequest received: {environ.get('PATH_INFO', '/')}")
return app(environ, start_response)
log("\n✓ APPLICATION READY - Check site now")
log("="*70)
except Exception as e:
log(f" ✗ Failed to import app:")
log(f" Error: {e}")
import traceback
log(f"\nFull traceback:")
log(traceback.format_exc())
# Create error application
def application(environ, start_response):
status = '500 Internal Server Error'
output = f'Import Error - Check {log_file}\n\n{traceback.format_exc()}'.encode('utf-8')
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
log("="*70)
except Exception as e:
# Catch-all for any errors
import traceback
log(f"\nFATAL ERROR during startup:")
log(str(e))
log(traceback.format_exc())
log("="*70)
def application(environ, start_response):
status = '500 Internal Server Error'
output = f'Startup Error - Check {log_file}'.encode('utf-8')
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
-44
View File
@@ -1,44 +0,0 @@
#!/usr/bin/env python3
"""
Fix Passenger Configuration
============================
This script renames the corrupted passenger_wsgi.py file so Passenger
will use the control panel settings instead.
"""
import os
import sys
def main():
print("=" * 70)
print("FIXING PASSENGER CONFIGURATION")
print("=" * 70)
# Check if passenger_wsgi.py exists
if os.path.exists('passenger_wsgi.py'):
print("\nFound passenger_wsgi.py - this file is causing the problem")
print("Renaming it to passenger_wsgi.py.DISABLED...")
try:
os.rename('passenger_wsgi.py', 'passenger_wsgi.py.DISABLED')
print("SUCCESS: passenger_wsgi.py renamed to passenger_wsgi.py.DISABLED")
print("\nPassenger will now use the control panel settings:")
print(" Application startup file: wsgi.py")
print(" Application Entry point: app")
except Exception as e:
print(f"ERROR: Could not rename file: {e}")
return 1
else:
print("\npassenger_wsgi.py not found - already fixed or doesn't exist")
print("\n" + "=" * 70)
print("NEXT STEPS:")
print("=" * 70)
print("1. Restart your Python application in the control panel")
print("2. Visit: https://columbiawindows.com/product-finder/test")
print("3. If it works, you're done!")
print("=" * 70)
return 0
if __name__ == '__main__':
sys.exit(main())
-64
View File
@@ -1,64 +0,0 @@
#!/bin/bash
# Fix Passenger lock file permissions
# Run this on the server to resolve "Can't acquire lock" error
echo "=========================================="
echo "FIXING PASSENGER LOCK FILE ISSUES"
echo "=========================================="
echo ""
# Navigate to app directory
cd ~/product-finder
# Remove any stale lock files
echo "🧹 Cleaning stale lock files..."
if [ -d "tmp" ]; then
rm -rf tmp/*
echo " ✓ tmp directory cleaned"
else
echo " ⚠️ tmp directory doesn't exist - will create it"
fi
# Create tmp directory with correct permissions
echo ""
echo "📁 Setting up tmp directory..."
mkdir -p tmp
chmod 755 tmp
echo " ✓ tmp directory created with 755 permissions"
# Create restart file
echo ""
echo "🔄 Restarting Passenger..."
touch tmp/restart.txt
chmod 644 tmp/restart.txt
echo " ✓ tmp/restart.txt created"
# Set correct permissions for app files
echo ""
echo "🔒 Setting file permissions..."
chmod 755 .
chmod 644 passenger_wsgi.py
chmod 644 app.py
chmod 644 .htaccess
chmod -R 755 data 2>/dev/null || mkdir -p data && chmod 755 data
chmod -R 755 templates
chmod -R 755 static 2>/dev/null || true
echo " ✓ File permissions set"
# Show current tmp directory status
echo ""
echo "📊 Current tmp directory status:"
ls -la tmp/
echo ""
echo "=========================================="
echo "✓ LOCK FILE ISSUE FIXED"
echo "=========================================="
echo ""
echo "Next steps:"
echo "1. Wait 30 seconds for Passenger to restart"
echo "2. Test: https://columbiawindows.com/product-finder/"
echo ""
echo "If still failing, check error log:"
echo "tail -50 ~/logs/error_log"
echo ""
-295
View File
@@ -1,295 +0,0 @@
"""
Generate Bitwise Helper File for Product Classification
Creates a helper file with bitwise flags based on product attributes (columns G-S)
"""
import csv
import json
from collections import defaultdict
# Bit position definitions
BIT_DEFINITIONS = {
# Base Type (Bits 0-1)
'base_door': 0, # 2^0 = 1
'base_window': 1, # 2^1 = 2
# Product Flags (Bits 2-3)
'is_accessory': 2, # 2^2 = 4
'specific_item': 3, # 2^3 = 8
# Materials (Bits 4-5)
'material_aluminum': 4, # 2^4 = 16
'material_vinyl': 5, # 2^5 = 32
# Colors (Bits 6-11)
'color_black': 6, # 2^6 = 64
'color_white': 7, # 2^7 = 128
'color_bronze': 8, # 2^8 = 256
'color_tan': 9, # 2^9 = 512
'color_mill': 10, # 2^10 = 1024
'color_sandstone': 11, # 2^11 = 2048
}
# Sub-type bits will be assigned dynamically (starting at bit 12)
SUBTYPE_BIT_START = 12
def parse_bool(value):
"""Parse TRUE/FALSE string to boolean"""
if isinstance(value, str):
return value.strip().upper() == 'TRUE'
return bool(value)
def calculate_bit_value(row, subtype_map):
"""Calculate the bitwise value for a product row"""
bit_value = 0
explanation = []
# Base Type (Column G - index 6)
base_type = row[6].strip() if len(row) > 6 and row[6] else ""
if base_type.lower() == 'door':
bit_value |= (1 << BIT_DEFINITIONS['base_door'])
explanation.append('Door')
elif base_type.lower() == 'window':
bit_value |= (1 << BIT_DEFINITIONS['base_window'])
explanation.append('Window')
# Accessory Flag (Column J - index 9)
if len(row) > 9 and parse_bool(row[9]):
bit_value |= (1 << BIT_DEFINITIONS['is_accessory'])
explanation.append('Accessory')
# Specific Item Link (Column K - index 10)
if len(row) > 10 and parse_bool(row[10]):
bit_value |= (1 << BIT_DEFINITIONS['specific_item'])
explanation.append('SpecificItem')
# Materials
if len(row) > 11 and parse_bool(row[11]): # Aluminum (Column L)
bit_value |= (1 << BIT_DEFINITIONS['material_aluminum'])
explanation.append('Aluminum')
if len(row) > 12 and parse_bool(row[12]): # Vinyl (Column M)
bit_value |= (1 << BIT_DEFINITIONS['material_vinyl'])
explanation.append('Vinyl')
# Colors
color_columns = [
(13, 'color_black', 'Black'),
(14, 'color_white', 'White'),
(15, 'color_bronze', 'Bronze'),
(16, 'color_tan', 'Tan'),
(17, 'color_mill', 'Mill'),
(18, 'color_sandstone', 'Sandstone'),
]
for col_idx, bit_key, color_name in color_columns:
if len(row) > col_idx and parse_bool(row[col_idx]):
bit_value |= (1 << BIT_DEFINITIONS[bit_key])
explanation.append(color_name)
# Sub-types (Columns H and I - indices 7 and 8)
door_subtype = row[7].strip() if len(row) > 7 and row[7] else ""
window_subtype = row[8].strip() if len(row) > 8 and row[8] else ""
if door_subtype and door_subtype in subtype_map:
bit_pos = subtype_map[door_subtype]
bit_value |= (1 << bit_pos)
explanation.append(f'Subtype:{door_subtype}')
if window_subtype and window_subtype in subtype_map:
bit_pos = subtype_map[window_subtype]
bit_value |= (1 << bit_pos)
explanation.append(f'Subtype:{window_subtype}')
return bit_value, explanation
def collect_subtypes(csv_path):
"""Collect all unique sub-types from the CSV"""
subtypes = set()
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader) # Skip first header row
next(reader) # Skip second header row
for row in reader:
if len(row) < 8:
continue
# Skip discontinued items
if len(row) > 0 and parse_bool(row[0]):
continue
# Collect door subtype (column H - index 7)
if len(row) > 7 and row[7].strip():
subtypes.add(row[7].strip())
# Collect window subtype (column I - index 8)
if len(row) > 8 and row[8].strip():
subtypes.add(row[8].strip())
return sorted(subtypes)
def generate_helper_files(csv_path):
"""Generate helper CSV and JSON files with bitwise values"""
print("Analyzing product data...")
# First pass: collect all unique sub-types
subtypes = collect_subtypes(csv_path)
# Create subtype bit mapping
subtype_map = {}
for idx, subtype in enumerate(subtypes):
subtype_map[subtype] = SUBTYPE_BIT_START + idx
print(f"Found {len(subtypes)} unique sub-types")
# Second pass: calculate bit values
results = []
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader) # Skip first header row
next(reader) # Skip second header row
for row in reader:
if len(row) < 3:
continue
prod_code = row[2].strip() # Column C - PROD_CODE
discontinued = parse_bool(row[0]) # Column A - DISCONT
bit_value, explanation = calculate_bit_value(row, subtype_map)
results.append({
'PROD_CODE': prod_code,
'BIT_VALUE': bit_value,
'BIT_HEX': f"0x{bit_value:X}",
'BIT_BINARY': f"{bit_value:b}",
'DISCONTINUED': discontinued,
'FLAGS': ' | '.join(explanation) if explanation else 'None'
})
# Filter out discontinued products for output files
active_results = [r for r in results if not r['DISCONTINUED']]
print(f"Total products processed: {len(results)}")
print(f"Active products: {len(active_results)}")
print(f"Discontinued products (filtered out): {len(results) - len(active_results)}")
# Write CSV helper file (only active products)
csv_output = 'data/product_bitwise.csv'
with open(csv_output, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['PROD_CODE', 'BIT_VALUE', 'BIT_HEX', 'BIT_BINARY', 'DISCONTINUED', 'FLAGS'])
writer.writeheader()
writer.writerows(active_results)
print(f"✓ Created {csv_output}")
# Write JSON helper file (only active products)
json_output = 'data/product_bitwise.json'
with open(json_output, 'w', encoding='utf-8') as f:
json.dump(active_results, f, indent=2)
print(f"✓ Created {json_output}")
# Create bit legend/documentation
legend = {
'description': 'Bitwise flag system for product classification',
'bit_definitions': {
'base_attributes': {
'bit_0 (1)': 'Base Type = Door',
'bit_1 (2)': 'Base Type = Window',
'bit_2 (4)': 'Is Accessory',
'bit_3 (8)': 'Specific Item Link',
},
'materials': {
'bit_4 (16)': 'Material = Aluminum',
'bit_5 (32)': 'Material = Vinyl',
},
'colors': {
'bit_6 (64)': 'Color = Black',
'bit_7 (128)': 'Color = White',
'bit_8 (256)': 'Color = Bronze',
'bit_9 (512)': 'Color = Tan',
'bit_10 (1024)': 'Color = Mill',
'bit_11 (2048)': 'Color = Sandstone',
},
'subtypes': {}
},
'usage_examples': {
'check_if_door': 'bit_value & 1',
'check_if_window': 'bit_value & 2',
'check_if_aluminum': 'bit_value & 16',
'check_if_white': 'bit_value & 128',
'check_multiple': '(bit_value & 1) and (bit_value & 16) # Door AND Aluminum',
}
}
# Add subtype mappings to legend
for subtype, bit_pos in sorted(subtype_map.items(), key=lambda x: x[1]):
bit_value = 1 << bit_pos
legend['bit_definitions']['subtypes'][f'bit_{bit_pos} ({bit_value})'] = f'Subtype = {subtype}'
legend['usage_examples'][f'check_subtype_{subtype.replace(" ", "_").lower()}'] = f'bit_value & {bit_value}'
# Write legend file
legend_output = 'data/bitwise_legend.json'
with open(legend_output, 'w', encoding='utf-8') as f:
json.dump(legend, f, indent=2)
print(f"✓ Created {legend_output}")
# Generate statistics
stats = {
'total_products': len([r for r in results if not r['DISCONTINUED']]),
'total_discontinued': len([r for r in results if r['DISCONTINUED']]),
'total_accessories': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 4)]),
'doors': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 1)]),
'windows': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 2)]),
'aluminum_products': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 16)]),
'vinyl_products': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 32)]),
'multi_material': len([r for r in results if not r['DISCONTINUED'] and (r['BIT_VALUE'] & 16) and (r['BIT_VALUE'] & 32)]),
}
print("\n" + "="*60)
print("STATISTICS")
print("="*60)
print(f"Total Active Products: {stats['total_products']}")
print(f"Total Discontinued: {stats['total_discontinued']}")
print(f"Accessories: {stats['total_accessories']}")
print(f"Doors: {stats['doors']}")
print(f"Windows: {stats['windows']}")
print(f"Aluminum Products: {stats['aluminum_products']}")
print(f"Vinyl Products: {stats['vinyl_products']}")
print(f"Multi-Material Products: {stats['multi_material']}")
print(f"Unique Sub-types: {len(subtypes)}")
print("="*60)
# Show example products
print("\nEXAMPLE PRODUCTS:")
print("-"*60)
for i, result in enumerate(active_results[:5]):
print(f"{result['PROD_CODE']:12} | {result['BIT_VALUE']:6} | {result['BIT_HEX']:8} | {result['FLAGS']}")
print("-"*60)
return active_results, legend, subtype_map
if __name__ == '__main__':
csv_path = 'data/products.csv'
try:
results, legend, subtype_map = generate_helper_files(csv_path)
print("\n✓ All helper files generated successfully!")
print("\nGenerated files:")
print(" - data/product_bitwise.csv (CSV format with bit values)")
print(" - data/product_bitwise.json (JSON format with bit values)")
print(" - data/bitwise_legend.json (Bit mapping documentation)")
except FileNotFoundError:
print(f"Error: Could not find {csv_path}")
print("Make sure products.csv exists in the data/ folder")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
-297
View File
@@ -1,297 +0,0 @@
"""
Dynamic Product Image Generator
Generates product images with configurable colors, hardware positions, and other options.
Uses PIL/Pillow for image manipulation.
"""
import os
import json
import hashlib
from io import BytesIO
from PIL import Image, ImageDraw, ImageEnhance, ImageColor
from pathlib import Path
class ProductImageGenerator:
"""Handles dynamic generation of product images based on configuration."""
def __init__(self, config_file='data/image_configs.json'):
"""Initialize with configuration file."""
self.config_file = config_file
self.configs = self._load_configs()
self.cache_dir = Path('cache/product_images')
self.cache_dir.mkdir(parents=True, exist_ok=True)
def _load_configs(self):
"""Load image configuration from JSON file."""
try:
with open(self.config_file, 'r') as f:
return json.load(f)
except Exception as e:
print(f"Error loading image configs: {e}")
return {}
def _find_image(self, image_path):
"""
Find image file, trying different extensions if needed.
Args:
image_path: Path to image (e.g., 'images/cobrai.jpg')
Returns:
Actual path to image file, or None if not found
"""
# Try the exact path first
if os.path.exists(image_path):
return image_path
# Get base path without extension
base_path = os.path.splitext(image_path)[0]
# Try common image extensions
for ext in ['.png', '.jpg', '.jpeg', '.PNG', '.JPG', '.JPEG']:
test_path = base_path + ext
if os.path.exists(test_path):
return test_path
return None
def generate_product_image(self, product_code, color='white', hinge='right',
material='aluminum', use_cache=True):
"""
Generate a product image with specified configuration.
Args:
product_code: Product identifier (e.g., 'cobrai')
color: Color name (e.g., 'white', 'black', 'bronze')
hinge: Hinge side ('right' or 'left')
material: Material type (for future use)
use_cache: Whether to use cached images
Returns:
PIL Image object
"""
product_code = product_code.lower()
# Check if product config exists
if product_code not in self.configs:
raise ValueError(f"Product {product_code} not found in configuration")
config = self.configs[product_code]
# Check cache first
if use_cache:
cache_key = self._get_cache_key(product_code, color, hinge, material)
cached_image = self._get_cached_image(cache_key)
if cached_image:
return cached_image
# Load base image
base_image_path = config['sourceImage']
# Try to find the image with different extensions if needed
image_path = self._find_image(base_image_path)
if not image_path:
raise FileNotFoundError(f"Could not load base image: {base_image_path}. Tried .jpg, .png, .jpeg")
try:
base_image = Image.open(image_path).convert('RGBA')
except Exception as e:
raise FileNotFoundError(f"Could not load base image: {image_path}. Error: {e}")
# Apply color to regions
if color in config['availableColors']:
color_rgb = tuple(config['availableColors'][color]['rgb'])
base_image = self._apply_color_to_regions(
base_image,
config['colorableRegions'],
color_rgb
)
# Apply hardware (handles, locks)
if hinge in config.get('hardwarePositions', {}):
base_image = self._apply_hardware(
base_image,
config['hardwarePositions'],
hinge
)
# Flip image if left hinge
if hinge == 'left':
base_image = base_image.transpose(Image.FLIP_LEFT_RIGHT)
# Cache the result
if use_cache:
self._cache_image(cache_key, base_image)
return base_image
def _apply_color_to_regions(self, image, regions, target_color):
"""
Apply color to specific regions of the image.
This method attempts to recolor the frame/panel areas while preserving
shadows, highlights, and texture.
"""
img_copy = image.copy()
pixels = img_copy.load()
width, height = img_copy.size
# Get the average brightness of the target color
target_brightness = sum(target_color) / 3
for region in regions:
x1, y1 = region['topLeft']
x2, y2 = region['bottomRight']
# Ensure coordinates are within bounds
x1 = max(0, min(x1, width - 1))
x2 = max(0, min(x2, width))
y1 = max(0, min(y1, height - 1))
y2 = max(0, min(y2, height))
# Apply color to region while preserving luminosity
for y in range(y1, y2):
for x in range(x1, x2):
try:
r, g, b, a = pixels[x, y]
# Calculate original brightness
original_brightness = (r + g + b) / 3
# Preserve relative brightness
if original_brightness > 0:
brightness_factor = original_brightness / 255.0
# Apply target color with brightness preservation
new_r = int(target_color[0] * brightness_factor)
new_g = int(target_color[1] * brightness_factor)
new_b = int(target_color[2] * brightness_factor)
# Ensure values are in valid range
new_r = max(0, min(255, new_r))
new_g = max(0, min(255, new_g))
new_b = max(0, min(255, new_b))
pixels[x, y] = (new_r, new_g, new_b, a)
except IndexError:
continue
return img_copy
def _apply_hardware(self, image, hardware_positions, hinge_side):
"""Apply hardware (handles, locks) to the image."""
img_copy = image.copy()
hardware_key = f"handle_{hinge_side}"
if hardware_key in hardware_positions:
hardware_config = hardware_positions[hardware_key]
hardware_path = hardware_config.get('image')
if hardware_path:
# Try to find the hardware image with different extensions
actual_path = self._find_image(hardware_path)
if actual_path:
try:
hardware_img = Image.open(actual_path).convert('RGBA')
# Flip if needed
if hardware_config.get('flip', False):
hardware_img = hardware_img.transpose(Image.FLIP_LEFT_RIGHT)
# Paste hardware at specified position
x, y = hardware_config['x'], hardware_config['y']
img_copy.paste(hardware_img, (x, y), hardware_img)
except Exception as e:
print(f"Could not apply hardware: {e}")
return img_copy
def _get_cache_key(self, product_code, color, hinge, material):
"""Generate a unique cache key for the configuration."""
key_string = f"{product_code}_{color}_{hinge}_{material}"
return hashlib.md5(key_string.encode()).hexdigest()
def _get_cached_image(self, cache_key):
"""Retrieve cached image if available."""
cache_path = self.cache_dir / f"{cache_key}.png"
if cache_path.exists():
try:
return Image.open(cache_path)
except Exception:
return None
return None
def _cache_image(self, cache_key, image):
"""Save image to cache."""
cache_path = self.cache_dir / f"{cache_key}.png"
try:
image.save(cache_path, 'PNG', optimize=True)
except Exception as e:
print(f"Could not cache image: {e}")
def get_product_config(self, product_code):
"""Get configuration for a specific product."""
return self.configs.get(product_code.lower())
def clear_cache(self, product_code=None):
"""Clear cached images. If product_code provided, only clear that product's cache."""
if product_code:
# Clear specific product cache (would need to track cache keys)
pass
else:
# Clear all cache
for cache_file in self.cache_dir.glob('*.png'):
try:
cache_file.unlink()
except Exception:
pass
def recolor_image_advanced(image, source_color_range, target_color):
"""
Advanced recoloring that replaces pixels within a color range.
Args:
image: PIL Image
source_color_range: Dict with 'min' and 'max' RGB tuples
target_color: Target RGB tuple
"""
img_copy = image.copy()
pixels = img_copy.load()
width, height = img_copy.size
min_r, min_g, min_b = source_color_range['min']
max_r, max_g, max_b = source_color_range['max']
for y in range(height):
for x in range(width):
r, g, b, a = pixels[x, y]
# Check if pixel is within source color range
if (min_r <= r <= max_r and
min_g <= g <= max_g and
min_b <= b <= max_b):
# Calculate brightness factor
brightness = (r + g + b) / 3 / 255.0
# Apply target color with brightness
new_r = int(target_color[0] * brightness)
new_g = int(target_color[1] * brightness)
new_b = int(target_color[2] * brightness)
pixels[x, y] = (new_r, new_g, new_b, a)
return img_copy
def image_to_base64(image, format='PNG'):
"""Convert PIL Image to base64 string."""
import base64
buffered = BytesIO()
image.save(buffered, format=format)
img_str = base64.b64encode(buffered.getvalue()).decode()
return f"data:image/{format.lower()};base64,{img_str}"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 959 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 MiB

-451
View File
@@ -1,451 +0,0 @@
/**
* Product Encoding/Decoding Helper
*
* Provides functions to encode and decode product configurations into compact
* hex-based URL strings. Uses bit-packing for efficient, stable encoding.
*
* Format: v-T-C-M-HHHH-HHHH-HHHH
* See /planning/ENCODING_SYSTEM.md for detailed documentation
*/
// ============================================================================
// LOOKUP TABLES
// ============================================================================
const ENCODING_VERSION = 0;
// Main Product Attributes (single hex character, 0-15)
const PRODUCT_TYPE = {
'PATIO_DOOR': 1,
'STORM_DOOR': 3,
'STORM_WINDOW': 5,
'PRIMARY_WINDOW': 7
};
const PRODUCT_TYPE_REVERSE = {
1: 'PATIO_DOOR',
3: 'STORM_DOOR',
5: 'STORM_WINDOW',
7: 'PRIMARY_WINDOW'
};
const PRODUCT_COLOR = {
'BLACK': 1,
'BRONZE': 2,
'SANDSTONE': 3,
'WHITE': 4,
'TAN': 5,
'MILL': 6
};
const PRODUCT_COLOR_REVERSE = {
1: 'BLACK',
2: 'BRONZE',
3: 'SANDSTONE',
4: 'WHITE',
5: 'TAN',
6: 'MILL'
};
const PRODUCT_MATERIAL = {
'ALUMINUM': 1,
'VINYL': 2
};
const PRODUCT_MATERIAL_REVERSE = {
1: 'ALUMINUM',
2: 'VINYL'
};
// Hardware Fields (5 bits each, 0-31)
const HARDWARE_TYPE = {
'NONE': 0,
'LEVER': 1,
'PULL': 2,
'PULL_HANDLE': 3,
'DEADBOLT': 4,
'HINGE': 5
};
const HARDWARE_TYPE_REVERSE = {
0: 'NONE',
1: 'LEVER',
2: 'PULL',
3: 'PULL_HANDLE',
4: 'DEADBOLT',
5: 'HINGE'
};
const HARDWARE_STYLE = {
'NONE': 0,
'STANDARD': 1,
'PUSH': 2,
'ALTERNATIVE': 3,
'CONTEMPORARY': 4,
'TRADITIONAL': 5
};
const HARDWARE_STYLE_REVERSE = {
0: 'NONE',
1: 'STANDARD',
2: 'PUSH',
3: 'ALTERNATIVE',
4: 'CONTEMPORARY',
5: 'TRADITIONAL'
};
const HARDWARE_COLOR = {
'NONE': 0,
'BRASS': 1,
'WHITE': 2,
'BLACK': 3,
'SATIN': 4,
'NICKEL': 5,
'BRONZE': 6
};
const HARDWARE_COLOR_REVERSE = {
0: 'NONE',
1: 'BRASS',
2: 'WHITE',
3: 'BLACK',
4: 'SATIN',
5: 'NICKEL',
6: 'BRONZE'
};
// ============================================================================
// ENCODING FUNCTIONS
// ============================================================================
/**
* Encode a hardware configuration into a 4-character hex string
* Uses 5 bits per field (32 values each)
*
* @param {number} type - Hardware type (0-31)
* @param {number} style - Hardware style (0-31)
* @param {number} color - Hardware color (0-31)
* @returns {string} 4-character hex string (e.g., "0421")
*/
function encodeHardware(type, style, color) {
// Validate inputs
if (type < 0 || type > 31) throw new Error(`Invalid hardware type: ${type} (must be 0-31)`);
if (style < 0 || style > 31) throw new Error(`Invalid hardware style: ${style} (must be 0-31)`);
if (color < 0 || color > 31) throw new Error(`Invalid hardware color: ${color} (must be 0-31)`);
// Pack into 16 bits: [reserved(1)][type(5)][style(5)][color(5)]
const value = ((type & 0x1F) << 10) | // Bits 10-14
((style & 0x1F) << 5) | // Bits 5-9
(color & 0x1F); // Bits 0-4
return value.toString(16).toUpperCase().padStart(4, '0');
}
/**
* Encode a complete product configuration into a URL string
*
* @param {Object} config - Product configuration
* @param {number} config.type - Product type (0-15)
* @param {number} config.color - Product color (0-15)
* @param {number} config.material - Product material (0-15)
* @param {Array<Object>} config.hardware - Array of hardware items (optional)
* @param {number} config.hardware[].type - Hardware type (0-31)
* @param {number} config.hardware[].style - Hardware style (0-31)
* @param {number} config.hardware[].color - Hardware color (0-31)
* @returns {string} Encoded URL string (e.g., "0-1-4-1-0421")
*/
function encodeProduct(config) {
// Validate main attributes
if (config.type < 0 || config.type > 15) {
throw new Error(`Invalid product type: ${config.type} (must be 0-15)`);
}
if (config.color < 0 || config.color > 15) {
throw new Error(`Invalid product color: ${config.color} (must be 0-15)`);
}
if (config.material < 0 || config.material > 15) {
throw new Error(`Invalid product material: ${config.material} (must be 0-15)`);
}
// Build base string: version-type-color-material
const parts = [
ENCODING_VERSION.toString(16).toUpperCase(),
config.type.toString(16).toUpperCase(),
config.color.toString(16).toUpperCase(),
config.material.toString(16).toUpperCase()
];
// Add hardware items if present
if (config.hardware && config.hardware.length > 0) {
config.hardware.forEach(hw => {
parts.push(encodeHardware(hw.type, hw.style, hw.color));
});
}
return parts.join('-');
}
/**
* Encode using named constants (convenience function)
*
* @param {Object} config - Product configuration with named values
* @param {string} config.type - Product type name (e.g., 'PATIO_DOOR')
* @param {string} config.color - Color name (e.g., 'WHITE')
* @param {string} config.material - Material name (e.g., 'ALUMINUM')
* @param {Array<Object>} config.hardware - Array of hardware items (optional)
* @returns {string} Encoded URL string
*/
function encodeProductByName(config) {
const numericConfig = {
type: PRODUCT_TYPE[config.type],
color: PRODUCT_COLOR[config.color],
material: PRODUCT_MATERIAL[config.material],
hardware: []
};
if (config.hardware && config.hardware.length > 0) {
numericConfig.hardware = config.hardware.map(hw => ({
type: HARDWARE_TYPE[hw.type],
style: HARDWARE_STYLE[hw.style],
color: HARDWARE_COLOR[hw.color]
}));
}
return encodeProduct(numericConfig);
}
// ============================================================================
// DECODING FUNCTIONS
// ============================================================================
/**
* Decode a hardware hex string back to its components
*
* @param {string} hex - 4-character hex string (e.g., "0421")
* @returns {Object} Decoded hardware configuration
*/
function decodeHardware(hex) {
if (typeof hex !== 'string' || hex.length !== 4) {
throw new Error(`Invalid hardware hex string: ${hex} (must be 4 characters)`);
}
const value = parseInt(hex, 16);
if (isNaN(value)) {
throw new Error(`Invalid hex value: ${hex}`);
}
return {
type: (value >> 10) & 0x1F, // Extract bits 10-14
style: (value >> 5) & 0x1F, // Extract bits 5-9
color: value & 0x1F // Extract bits 0-4
};
}
/**
* Decode a complete product URL string
*
* @param {string} encodedString - Encoded URL string (e.g., "0-1-4-1-0421")
* @returns {Object} Decoded product configuration
*/
function decodeProduct(encodedString) {
if (typeof encodedString !== 'string') {
throw new Error('Invalid encoded string: must be a string');
}
const parts = encodedString.split('-');
if (parts.length < 4) {
throw new Error(`Invalid encoded string: ${encodedString} (must have at least 4 parts)`);
}
// Parse version
const version = parseInt(parts[0], 16);
if (version !== ENCODING_VERSION) {
throw new Error(`Unsupported encoding version: ${version} (current: ${ENCODING_VERSION})`);
}
// Parse main attributes
const config = {
version: version,
type: parseInt(parts[1], 16),
color: parseInt(parts[2], 16),
material: parseInt(parts[3], 16),
hardware: []
};
// Parse hardware items (if present)
for (let i = 4; i < parts.length; i++) {
config.hardware.push(decodeHardware(parts[i]));
}
return config;
}
/**
* Decode and return named values (convenience function)
*
* @param {string} encodedString - Encoded URL string
* @returns {Object} Decoded product with named values
*/
function decodeProductToNames(encodedString) {
const numeric = decodeProduct(encodedString);
return {
version: numeric.version,
type: PRODUCT_TYPE_REVERSE[numeric.type] || `UNKNOWN_${numeric.type}`,
color: PRODUCT_COLOR_REVERSE[numeric.color] || `UNKNOWN_${numeric.color}`,
material: PRODUCT_MATERIAL_REVERSE[numeric.material] || `UNKNOWN_${numeric.material}`,
hardware: numeric.hardware.map(hw => ({
type: HARDWARE_TYPE_REVERSE[hw.type] || `UNKNOWN_${hw.type}`,
style: HARDWARE_STYLE_REVERSE[hw.style] || `UNKNOWN_${hw.style}`,
color: HARDWARE_COLOR_REVERSE[hw.color] || `UNKNOWN_${hw.color}`
}))
};
}
// ============================================================================
// UTILITY FUNCTIONS
// ============================================================================
/**
* Get the binary representation of a hex string (for debugging)
*
* @param {string} hex - Hex string
* @returns {string} Binary string with spaces every 4 bits
*/
function hexToBinary(hex) {
const value = parseInt(hex, 16);
const binary = value.toString(2).padStart(16, '0');
return binary.match(/.{1,4}/g).join(' ');
}
/**
* Validate that a configuration uses only defined values
*
* @param {Object} config - Product configuration
* @returns {Object} Validation result with errors array
*/
function validateConfiguration(config) {
const errors = [];
if (!PRODUCT_TYPE_REVERSE[config.type]) {
errors.push(`Invalid product type: ${config.type}`);
}
if (!PRODUCT_COLOR_REVERSE[config.color]) {
errors.push(`Invalid product color: ${config.color}`);
}
if (!PRODUCT_MATERIAL_REVERSE[config.material]) {
errors.push(`Invalid product material: ${config.material}`);
}
if (config.hardware) {
config.hardware.forEach((hw, index) => {
if (!HARDWARE_TYPE_REVERSE[hw.type]) {
errors.push(`Invalid hardware ${index + 1} type: ${hw.type}`);
}
if (!HARDWARE_STYLE_REVERSE[hw.style]) {
errors.push(`Invalid hardware ${index + 1} style: ${hw.style}`);
}
if (!HARDWARE_COLOR_REVERSE[hw.color]) {
errors.push(`Invalid hardware ${index + 1} color: ${hw.color}`);
}
});
}
return {
valid: errors.length === 0,
errors: errors
};
}
// ============================================================================
// EXPORTS (for Node.js / Module usage)
// ============================================================================
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
// Constants
ENCODING_VERSION,
PRODUCT_TYPE,
PRODUCT_COLOR,
PRODUCT_MATERIAL,
HARDWARE_TYPE,
HARDWARE_STYLE,
HARDWARE_COLOR,
// Encoding functions
encodeHardware,
encodeProduct,
encodeProductByName,
// Decoding functions
decodeHardware,
decodeProduct,
decodeProductToNames,
// Utilities
hexToBinary,
validateConfiguration
};
}
// ============================================================================
// EXAMPLE USAGE
// ============================================================================
/*
// Example 1: Encode by numeric values
const encoded1 = encodeProduct({
type: 1, // Patio Door
color: 4, // White
material: 1, // Aluminum
hardware: [
{ type: 1, style: 1, color: 1 } // Lever, Standard, Brass
]
});
console.log(encoded1); // "0-1-4-1-0421"
// Example 2: Encode by named values
const encoded2 = encodeProductByName({
type: 'STORM_DOOR',
color: 'WHITE',
material: 'ALUMINUM',
hardware: [
{ type: 'LEVER', style: 'STANDARD', color: 'BRASS' },
{ type: 'PULL_HANDLE', style: 'ALTERNATIVE', color: 'SATIN' }
]
});
console.log(encoded2); // "0-3-4-1-0421-0C64"
// Example 3: Decode back to numeric values
const decoded1 = decodeProduct("0-1-4-1-0421");
console.log(decoded1);
// { version: 0, type: 1, color: 4, material: 1, hardware: [{ type: 1, style: 1, color: 1 }] }
// Example 4: Decode to named values
const decoded2 = decodeProductToNames("0-3-4-1-0421-0C64");
console.log(decoded2);
// {
// version: 0,
// type: 'STORM_DOOR',
// color: 'WHITE',
// material: 'ALUMINUM',
// hardware: [
// { type: 'LEVER', style: 'STANDARD', color: 'BRASS' },
// { type: 'PULL_HANDLE', style: 'ALTERNATIVE', color: 'SATIN' }
// ]
// }
// Example 5: Debug hardware encoding
const hwHex = encodeHardware(3, 12, 20);
console.log(hwHex); // "0D94"
console.log(hexToBinary(hwHex)); // "0000 1101 1001 0100"
console.log(decodeHardware(hwHex)); // { type: 3, style: 12, color: 20 }
// Example 6: Validate configuration
const validation = validateConfiguration({
type: 1, color: 4, material: 1,
hardware: [{ type: 1, style: 1, color: 1 }]
});
console.log(validation); // { valid: true, errors: [] }
*/
-652
View File
@@ -1,652 +0,0 @@
"""
CSV to JSON Parser - Generate Navigation, Products, and Accessories JSON Files
Based on AI_PARSING_INSTRUCTIONS.md
This script reads data/products.csv and generates:
1. data/navigation.json - Question flow with conditional logic
2. data/products.json - Product catalog
3. data/accessories.json - Accessory options with compatibility rules
Run: python parse_csv_to_json.py
"""
import csv
import json
from collections import defaultdict
from typing import Dict, List, Set, Tuple
def parse_bool(value):
"""Parse TRUE/FALSE string to boolean"""
if isinstance(value, str):
return value.strip().upper() == 'TRUE'
return bool(value)
def clean_string(value):
"""Clean and strip string values"""
if isinstance(value, str):
return value.strip()
return value or ""
class CSVParser:
def __init__(self, csv_path: str):
self.csv_path = csv_path
self.products = []
self.accessories = []
self.base_types = set()
self.door_subtypes = defaultdict(list) # subtype -> [products]
self.window_subtypes = defaultdict(list)
self.material_counts = defaultdict(lambda: {'aluminum': 0, 'vinyl': 0})
self.color_counts = defaultdict(lambda: defaultdict(int)) # subtype -> {color: count}
self.color_by_material = defaultdict(lambda: defaultdict(set)) # subtype -> {material: {colors}}
self.detailed_products = {} # Load from questions.json
def load_detailed_product_info(self):
"""Load detailed product info from questions.json"""
try:
# Load the code mapping
try:
with open('data/product_code_mapping.json', 'r', encoding='utf-8') as f:
code_mapping = json.load(f)
except FileNotFoundError:
code_mapping = {}
with open('data/questions.json', 'r', encoding='utf-8') as f:
questions_data = json.load(f)
# Extract all product nodes
for key, value in questions_data.items():
if key.startswith('prod-') and value.get('type') == 'product':
code = value.get('code')
if code:
detailed_info = {
'title': value.get('title'),
'detailedDescription': value.get('description'),
'features': value.get('features', []),
'image': value.get('image'),
'url': value.get('url'),
'brochure': value.get('brochure'),
'measureGuide': value.get('measureGuide')
}
# Store under the simplified code
self.detailed_products[code] = detailed_info
# Also store under all mapped codes
for csv_code, simple_code in code_mapping.items():
if simple_code == code:
self.detailed_products[csv_code] = detailed_info
print(f"✓ Loaded {len(self.detailed_products)} detailed product descriptions")
except FileNotFoundError:
print("⚠ questions.json not found - skipping detailed product info")
except Exception as e:
print(f"⚠ Error loading product details: {e}")
def parse_csv(self):
"""Parse the CSV file and separate products from accessories"""
print("📖 Reading CSV file...")
with open(self.csv_path, 'r', encoding='utf-8', errors='ignore') as f:
reader = csv.reader(f)
# Skip first two header rows
next(reader) # Row 1: Category headers
header_row = next(reader) # Row 2: Column names
row_count = 0
for row in reader:
if len(row) < 11: # Need at least up to column K
continue
row_count += 1
# Skip discontinued items
if parse_bool(row[0]): # DISCONT column
continue
# Extract basic info
prod_code = clean_string(row[2]) # PROD_CODE
category = clean_string(row[3]) # CATEGORY
description = clean_string(row[5]) # DESCRIPTION
location = clean_string(row[1]) # LOC_CODE
base_type = clean_string(row[6]) if len(row) > 6 else "" # Base Type (G)
door_subtype = clean_string(row[7]) if len(row) > 7 else "" # Sub-type Door (H)
window_subtype = clean_string(row[8]) if len(row) > 8 else "" # Sub-type Window (I)
is_accessory = parse_bool(row[9]) if len(row) > 9 else False # Accessory Yes (J)
specific_item = parse_bool(row[10]) if len(row) > 10 else False # This Item (K)
# Parse materials (L, M)
materials = []
if len(row) > 11 and parse_bool(row[11]):
materials.append('Aluminum')
if len(row) > 12 and parse_bool(row[12]):
materials.append('Vinyl')
# Parse colors (N through S+)
colors = []
color_columns = [
(13, 'Black'), (14, 'White'), (15, 'Bronze'),
(16, 'Tan'), (17, 'Mill'), (18, 'Sandstone')
]
for col_idx, color_name in color_columns:
if len(row) > col_idx and parse_bool(row[col_idx]):
colors.append(color_name)
# Build item data
item_data = {
'id': prod_code,
'productCode': prod_code,
'category': category,
'description': description,
'discontinued': False,
'location': location,
'baseType': base_type,
'subType': {
'door': door_subtype if door_subtype else None,
'window': window_subtype if window_subtype else None
},
'materials': materials,
'colors': colors
}
# Separate accessories from products
if is_accessory:
# Build accessory-specific data
accessory = {
**item_data,
'accessoryCode': prod_code,
'compatibilityRules': self._build_compatibility_rules(
door_subtype, window_subtype, category, specific_item
),
'optionType': self._infer_option_type(description),
'metadata': {
'specificItemLink': specific_item
}
}
self.accessories.append(accessory)
else:
# Build product-specific data
product = {
**item_data,
'isAccessory': False,
'compatibleAccessories': [] # Will be populated later
}
# Merge detailed info if available
if prod_code in self.detailed_products:
detailed = self.detailed_products[prod_code]
product.update({
'title': detailed['title'],
'detailedDescription': detailed['detailedDescription'],
'features': detailed['features'],
'image': detailed['image'],
'url': detailed['url'],
'brochure': detailed.get('brochure'),
'measureGuide': detailed.get('measureGuide')
})
self.products.append(product)
# Track for navigation building
if base_type:
self.base_types.add(base_type)
# Track subtypes per type
if door_subtype:
self.door_subtypes[door_subtype].append(product)
if window_subtype:
self.window_subtypes[window_subtype].append(product)
# Count materials per subtype
subtype_key = door_subtype or window_subtype or "none"
if 'Aluminum' in materials:
self.material_counts[subtype_key]['aluminum'] += 1
# Track colors per material
for color in colors:
self.color_by_material[subtype_key]['Aluminum'].add(color)
if 'Vinyl' in materials:
self.material_counts[subtype_key]['vinyl'] += 1
# Track colors per material
for color in colors:
self.color_by_material[subtype_key]['Vinyl'].add(color)
# Count colors per subtype (overall)
for color in colors:
self.color_counts[subtype_key][color] += 1
print(f"✓ Parsed {row_count} rows")
print(f"✓ Found {len(self.products)} products")
print(f"✓ Found {len(self.accessories)} accessories")
def _build_compatibility_rules(self, door_subtype, window_subtype, category, specific_item):
"""Build compatibility rules for accessories"""
rules = {
'type': 'category', # Default
'subTypeDoor': door_subtype if door_subtype else None,
'subTypeWindow': window_subtype if window_subtype else None,
'categories': [category] if category else [],
'specificProducts': [],
'requiresMatch': {
'material': True, # Usually accessories need matching material
'color': False # Colors usually don't need to match
}
}
# Determine rule type
if specific_item:
rules['type'] = 'specific'
elif door_subtype or window_subtype:
rules['type'] = 'subType'
return rules
def _infer_option_type(self, description):
"""Infer option type from description"""
desc_upper = description.upper()
if 'HANDLE' in desc_upper:
return 'handle'
elif 'INSERT' in desc_upper or 'GLASS' in desc_upper:
return 'insert'
elif 'HARDWARE' in desc_upper:
return 'hardware'
elif 'SCREEN' in desc_upper:
return 'screen'
else:
return 'option'
def link_accessories_to_products(self):
"""Link compatible accessories to products"""
print("🔗 Linking accessories to products...")
linked_count = 0
for product in self.products:
compatible = []
for accessory in self.accessories:
rules = accessory['compatibilityRules']
# Check by subtype
if rules['type'] == 'subType':
prod_door = product['subType']['door']
prod_window = product['subType']['window']
acc_door = rules['subTypeDoor']
acc_window = rules['subTypeWindow']
if (prod_door and prod_door == acc_door) or \
(prod_window and prod_window == acc_window):
# Check material compatibility if required
if rules['requiresMatch']['material']:
# Check if they share any materials
if any(m in product['materials'] for m in accessory['materials']):
compatible.append(accessory['id'])
linked_count += 1
else:
compatible.append(accessory['id'])
linked_count += 1
# Check by category
elif rules['type'] == 'category':
if product['category'] in rules['categories']:
compatible.append(accessory['id'])
linked_count += 1
product['compatibleAccessories'] = compatible
print(f"✓ Created {linked_count} product-accessory links")
def build_navigation(self):
"""Build navigation JSON with conditional logic"""
print("🗺️ Building navigation flow...")
navigation = {}
# Question 1: Base Type Selection
navigation['start'] = {
'type': 'question',
'inputType': 'button',
'title': 'What are you looking for?',
'subtitle': 'Select the product category',
'answers': []
}
# Add base type options
sorted_types = sorted(self.base_types)
for base_type in sorted_types:
emoji = '🚪' if 'door' in base_type.lower() else '🪟'
next_key = f'q-{base_type.lower()}-type'
navigation['start']['answers'].append({
'caption': base_type,
'image': emoji,
'next': next_key,
'filter': {
'baseType': base_type
}
})
# Question 2: Sub-type Selection for Doors
if self.door_subtypes:
door_subtypes = sorted(self.door_subtypes.keys())
navigation['q-door-type'] = {
'type': 'question',
'inputType': 'button',
'title': 'What type of door?',
'subtitle': 'Select the door category',
'answers': []
}
for subtype in door_subtypes:
products = self.door_subtypes[subtype]
# Check if material question is needed
needs_material = self._needs_material_question(subtype)
# Determine next question
if needs_material:
next_key = f'q-material-{subtype.lower().replace(" ", "-")}'
else:
# No material choice needed - determine single material and check colors
single_material = 'Aluminum' if self.material_counts[subtype]['aluminum'] > 0 else 'Vinyl'
needs_color = self._needs_color_question(subtype, single_material)
next_key = f'q-color-{subtype.lower().replace(" ", "-")}-{single_material.lower()}' if needs_color else 'q-dimensions'
# Auto-apply material if only one
filter_obj = {
'baseType': 'Door',
'subType': subtype
}
if not needs_material:
# Auto-apply the single material
if self.material_counts[subtype]['aluminum'] > 0:
filter_obj['material'] = 'Aluminum'
elif self.material_counts[subtype]['vinyl'] > 0:
filter_obj['material'] = 'Vinyl'
# If no color question either, auto-apply single color
single_material = filter_obj['material']
if not self._needs_color_question(subtype, single_material):
colors = list(self.color_by_material[subtype][single_material])
if len(colors) == 1:
filter_obj['color'] = colors[0]
navigation['q-door-type']['answers'].append({
'caption': subtype,
'image': '🚪',
'next': next_key,
'filter': filter_obj
})
# Create material question if needed
if needs_material:
self._create_material_question(navigation, subtype, 'Door')
# Create color question if material skipped but color needed
elif next_key.startswith('q-color-'):
single_material = 'Aluminum' if self.material_counts[subtype]['aluminum'] > 0 else 'Vinyl'
self._create_color_question(navigation, subtype, single_material, 'Door')
# Question 2: Sub-type Selection for Windows
if self.window_subtypes:
window_subtypes = sorted(self.window_subtypes.keys())
navigation['q-window-type'] = {
'type': 'question',
'inputType': 'button',
'title': 'What type of window?',
'subtitle': 'Select the window category',
'answers': []
}
for subtype in window_subtypes:
needs_material = self._needs_material_question(subtype)
# Determine next question
if needs_material:
next_key = f'q-material-{subtype.lower().replace(" ", "-")}'
else:
# No material choice needed - determine single material and check colors
single_material = 'Aluminum' if self.material_counts[subtype]['aluminum'] > 0 else 'Vinyl'
needs_color = self._needs_color_question(subtype, single_material)
next_key = f'q-color-{subtype.lower().replace(" ", "-")}-{single_material.lower()}' if needs_color else 'q-dimensions'
filter_obj = {
'baseType': 'Window',
'subType': subtype
}
if not needs_material:
if self.material_counts[subtype]['aluminum'] > 0:
filter_obj['material'] = 'Aluminum'
elif self.material_counts[subtype]['vinyl'] > 0:
filter_obj['material'] = 'Vinyl'
# If no color question either, auto-apply single color
single_material = filter_obj['material']
if not self._needs_color_question(subtype, single_material):
colors = list(self.color_by_material[subtype][single_material])
if len(colors) == 1:
filter_obj['color'] = colors[0]
navigation['q-window-type']['answers'].append({
'caption': subtype,
'image': '🪟',
'next': next_key,
'filter': filter_obj
})
if needs_material:
self._create_material_question(navigation, subtype, 'Window')
# Create color question if material skipped but color needed
elif next_key.startswith('q-color-'):
single_material = 'Aluminum' if self.material_counts[subtype]['aluminum'] > 0 else 'Vinyl'
self._create_color_question(navigation, subtype, single_material, 'Window')
# Final Question: Dimensions
navigation['q-dimensions'] = {
'type': 'question',
'inputType': 'form',
'title': 'Enter Product Dimensions',
'subtitle': 'Please provide the measurements',
'fields': [
{
'name': 'width',
'label': 'Width (inches)',
'type': 'number',
'required': True,
'placeholder': 'e.g., 36'
},
{
'name': 'height',
'label': 'Height (inches)',
'type': 'number',
'required': True,
'placeholder': 'e.g., 80'
}
],
'next': 'results'
}
print(f"✓ Created {len(navigation)} navigation nodes")
return navigation
def _needs_material_question(self, subtype):
"""Check if a subtype needs a material selection question"""
aluminum = self.material_counts[subtype]['aluminum']
vinyl = self.material_counts[subtype]['vinyl']
# Show material question if both materials exist
return aluminum > 0 and vinyl > 0
def _create_material_question(self, navigation, subtype, base_type):
"""Create a material selection question"""
question_key = f'q-material-{subtype.lower().replace(" ", "-")}'
navigation[question_key] = {
'type': 'question',
'inputType': 'button',
'title': 'Select Material',
'subtitle': f'Choose your preferred material for {subtype}',
'conditional': {
'type': 'material',
'fallbackNext': 'q-dimensions'
},
'answers': []
}
# Add material options
if self.material_counts[subtype]['aluminum'] > 0:
# Check if color question needed after aluminum selection
needs_color = self._needs_color_question(subtype, 'Aluminum')
next_key_al = f'q-color-{subtype.lower().replace(" ", "-")}-aluminum' if needs_color else 'q-dimensions'
navigation[question_key]['answers'].append({
'caption': 'Aluminum',
'image': '🔩',
'next': next_key_al,
'filter': {
'baseType': base_type,
'subType': subtype,
'material': 'Aluminum'
}
})
if self.material_counts[subtype]['vinyl'] > 0:
# Check if color question needed after vinyl selection
needs_color = self._needs_color_question(subtype, 'Vinyl')
next_key_vin = f'q-color-{subtype.lower().replace(" ", "-")}-vinyl' if needs_color else 'q-dimensions'
navigation[question_key]['answers'].append({
'caption': 'Vinyl',
'image': '🪟',
'next': next_key_vin,
'filter': {
'baseType': base_type,
'subType': subtype,
'material': 'Vinyl'
}
})
# Create color questions for each material option
if self.material_counts[subtype]['aluminum'] > 0 and self._needs_color_question(subtype, 'Aluminum'):
self._create_color_question(navigation, subtype, 'Aluminum', base_type)
if self.material_counts[subtype]['vinyl'] > 0 and self._needs_color_question(subtype, 'Vinyl'):
self._create_color_question(navigation, subtype, 'Vinyl', base_type)
def _needs_color_question(self, subtype, material):
"""Check if a subtype+material combination needs a color selection question"""
colors = self.color_by_material[subtype][material]
# Show color question if multiple colors exist
return len(colors) > 1
def _create_color_question(self, navigation, subtype, material, base_type):
"""Create a color selection question"""
question_key = f'q-color-{subtype.lower().replace(" ", "-")}-{material.lower()}'
navigation[question_key] = {
'type': 'question',
'inputType': 'button',
'title': 'Select Color',
'subtitle': f'Choose your preferred color for {material} {subtype}',
'conditional': {
'type': 'color',
'fallbackNext': 'q-dimensions'
},
'answers': []
}
# Get available colors for this subtype+material
colors = sorted(self.color_by_material[subtype][material])
# Color emoji mapping
color_emojis = {
'Black': '',
'White': '',
'Bronze': '🟫',
'Tan': '🟤',
'Mill': '',
'Sandstone': '🟨'
}
for color in colors:
navigation[question_key]['answers'].append({
'caption': color,
'image': color_emojis.get(color, '🎨'),
'next': 'q-dimensions',
'filter': {
'baseType': base_type,
'subType': subtype,
'material': material,
'color': color
}
})
def save_json_files(self, navigation):
"""Save all three JSON files"""
print("💾 Saving JSON files...")
# Save products.json
with open('data/products.json', 'w', encoding='utf-8') as f:
json.dump(self.products, f, indent=2)
print(f"✓ Saved data/products.json ({len(self.products)} products)")
# Save accessories.json
with open('data/accessories.json', 'w', encoding='utf-8') as f:
json.dump(self.accessories, f, indent=2)
print(f"✓ Saved data/accessories.json ({len(self.accessories)} accessories)")
# Save navigation.json
with open('data/navigation.json', 'w', encoding='utf-8') as f:
json.dump(navigation, f, indent=2)
print(f"✓ Saved data/navigation.json ({len(navigation)} nodes)")
def print_statistics(self):
"""Print parsing statistics"""
print("\n" + "="*60)
print("PARSING STATISTICS")
print("="*60)
print(f"Total Products: {len(self.products)}")
print(f"Total Accessories: {len(self.accessories)}")
print(f"Base Types: {', '.join(sorted(self.base_types))}")
print(f"Door Subtypes: {len(self.door_subtypes)}")
print(f"Window Subtypes: {len(self.window_subtypes)}")
print()
print("Material Distribution:")
for subtype, counts in sorted(self.material_counts.items()):
if counts['aluminum'] > 0 or counts['vinyl'] > 0:
needs_q = "✓ Material Q" if (counts['aluminum'] > 0 and counts['vinyl'] > 0) else "✗ Skip"
print(f" {subtype:20} - Al:{counts['aluminum']:3} Vinyl:{counts['vinyl']:3} [{needs_q}]")
print("="*60)
def main():
csv_path = 'data/products.csv'
print("🚀 CSV to JSON Parser")
print("="*60)
try:
parser = CSVParser(csv_path)
parser.load_detailed_product_info()
parser.parse_csv()
parser.link_accessories_to_products()
navigation = parser.build_navigation()
parser.save_json_files(navigation)
parser.print_statistics()
print("\n✅ All JSON files generated successfully!")
print("\nNext steps:")
print("1. Review data/navigation.json for question flow")
print("2. Review data/products.json for product data")
print("3. Review data/accessories.json for accessory compatibility")
print("4. Test the application in your browser")
except FileNotFoundError:
print(f"❌ Error: Could not find {csv_path}")
print(" Make sure products.csv exists in the data/ folder")
except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
if __name__ == '__main__':
main()
+12 -42
View File
@@ -1,47 +1,17 @@
"""
Passenger WSGI file for Flask application
Compatible with Python 3.13+
Auto-detects /product-finder subdirectory deployment
"""
import sys
import importlib.machinery
import importlib.util
import os
import sys
# Get the directory where this file is located
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
# Add the application directory to Python path
sys.path.insert(0, CURRENT_DIR)
sys.path.insert(0, os.path.dirname(__file__))
# Import the Flask application directly from app.py
# Note: app.py now auto-detects production environment
try:
from app import app as application
print("✓ Flask application loaded successfully")
except ImportError as e:
# Fallback error handler that shows the actual error
def application(environ, start_response):
import traceback
status = '500 Internal Server Error'
error_details = f'Import Error: {str(e)}\n\nTraceback:\n{traceback.format_exc()}\n\nPython Path:\n{sys.path}'
output = error_details.encode('utf-8')
response_headers = [('Content-type', 'text/plain; charset=utf-8'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
print(f"✗ Failed to import Flask app: {e}")
def load_source(modname, filename):
loader = importlib.machinery.SourceFileLoader(modname, filename)
spec = importlib.util.spec_from_file_location(modname, filename, loader=loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
except Exception as e:
# Catch any other startup errors
def application(environ, start_response):
import traceback
status = '500 Internal Server Error'
error_details = f'Startup Error: {str(e)}\n\nTraceback:\n{traceback.format_exc()}'
output = error_details.encode('utf-8')
response_headers = [('Content-type', 'text/plain; charset=utf-8'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
print(f"✗ Error starting app: {e}")
# Passenger requires the application object to be named 'application'
wsgi = load_source('wsgi', 'app.py')
application = wsgi.application
-189
View File
@@ -1,189 +0,0 @@
"""
Interactive Region Coordinate Helper
Opens an image and helps you find pixel coordinates for colorable regions.
Click on the image to see coordinates.
Usage:
python region_helper.py images/cobrai.jpg
"""
import sys
from PIL import Image, ImageDraw, ImageFont
import tkinter as tk
from tkinter import Canvas
from PIL import ImageTk
class RegionHelper:
def __init__(self, image_path):
self.image_path = image_path
self.image = Image.open(image_path)
self.width, self.height = self.image.size
# Setup UI
self.root = tk.Tk()
self.root.title(f"Region Helper - {image_path}")
# Scale image if too large
self.scale = 1.0
max_display_width = 1000
max_display_height = 800
if self.width > max_display_width or self.height > max_display_height:
scale_w = max_display_width / self.width
scale_h = max_display_height / self.height
self.scale = min(scale_w, scale_h)
new_width = int(self.width * self.scale)
new_height = int(self.height * self.scale)
self.display_image = self.image.resize((new_width, new_height), Image.LANCZOS)
else:
self.display_image = self.image.copy()
# Setup canvas
self.canvas = Canvas(
self.root,
width=self.display_image.width,
height=self.display_image.height
)
self.canvas.pack(side=tk.LEFT)
# Display image
self.photo = ImageTk.PhotoImage(self.display_image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)
# Info panel
info_frame = tk.Frame(self.root, width=300)
info_frame.pack(side=tk.RIGHT, fill=tk.BOTH, padx=10, pady=10)
tk.Label(info_frame, text="Image Dimensions:", font=('Arial', 12, 'bold')).pack(anchor=tk.W, pady=5)
tk.Label(info_frame, text=f"{self.width} x {self.height} pixels").pack(anchor=tk.W)
if self.scale != 1.0:
tk.Label(info_frame, text=f"Scaled: {self.scale:.2%}").pack(anchor=tk.W)
tk.Label(info_frame, text="\nClick to get coordinates:", font=('Arial', 12, 'bold')).pack(anchor=tk.W, pady=(20, 5))
self.coord_label = tk.Label(info_frame, text="X: -, Y: -", font=('Arial', 14))
self.coord_label.pack(anchor=tk.W, pady=5)
tk.Label(info_frame, text="\nFirst click = Top-Left", fg='blue').pack(anchor=tk.W)
tk.Label(info_frame, text="Second click = Bottom-Right", fg='blue').pack(anchor=tk.W)
tk.Label(info_frame, text="\nRegion JSON:", font=('Arial', 12, 'bold')).pack(anchor=tk.W, pady=(20, 5))
self.json_text = tk.Text(info_frame, height=15, width=35, font=('Courier', 9))
self.json_text.pack(fill=tk.BOTH, expand=True)
tk.Button(info_frame, text="Clear Points", command=self.clear_points).pack(pady=10)
tk.Button(info_frame, text="Copy JSON", command=self.copy_json).pack()
# Bind events
self.canvas.bind('<Motion>', self.on_mouse_move)
self.canvas.bind('<Button-1>', self.on_click)
# Store points
self.points = []
self.point_ids = []
self.update_json()
def on_mouse_move(self, event):
"""Show current mouse coordinates."""
x = int(event.x / self.scale)
y = int(event.y / self.scale)
self.coord_label.config(text=f"X: {x}, Y: {y}")
def on_click(self, event):
"""Record clicked point."""
x = int(event.x / self.scale)
y = int(event.y / self.scale)
# Limit to 2 points (top-left, bottom-right)
if len(self.points) >= 2:
self.clear_points()
self.points.append((x, y))
# Draw point on canvas
color = 'blue' if len(self.points) == 1 else 'red'
point_id = self.canvas.create_oval(
event.x - 5, event.y - 5,
event.x + 5, event.y + 5,
fill=color, outline='white', width=2
)
self.point_ids.append(point_id)
# Draw rectangle if we have both points
if len(self.points) == 2:
x1, y1 = self.points[0]
x2, y2 = self.points[1]
# Draw on canvas (scaled)
rect_id = self.canvas.create_rectangle(
x1 * self.scale, y1 * self.scale,
x2 * self.scale, y2 * self.scale,
outline='green', width=2, dash=(5, 5)
)
self.point_ids.append(rect_id)
self.update_json()
def clear_points(self):
"""Clear all points and rectangles."""
for point_id in self.point_ids:
self.canvas.delete(point_id)
self.points = []
self.point_ids = []
self.update_json()
def update_json(self):
"""Update the JSON display."""
self.json_text.delete('1.0', tk.END)
if len(self.points) == 0:
self.json_text.insert('1.0', '{\n "name": "region_name",\n "topLeft": [?, ?],\n "bottomRight": [?, ?],\n "description": "..."\n}')
elif len(self.points) == 1:
x, y = self.points[0]
self.json_text.insert('1.0', f'{{\n "name": "region_name",\n "topLeft": [{x}, {y}],\n "bottomRight": [?, ?],\n "description": "..."\n}}')
else:
x1, y1 = self.points[0]
x2, y2 = self.points[1]
# Calculate dimensions
width = abs(x2 - x1)
height = abs(y2 - y1)
json_str = f'''{{\n "name": "region_name",\n "topLeft": [{x1}, {y1}],\n "bottomRight": [{x2}, {y2}],\n "description": "Width: {width}px, Height: {height}px"\n}}'''
self.json_text.insert('1.0', json_str)
def copy_json(self):
"""Copy JSON to clipboard."""
json_str = self.json_text.get('1.0', tk.END).strip()
self.root.clipboard_clear()
self.root.clipboard_append(json_str)
self.root.update()
def run(self):
"""Start the GUI."""
self.root.mainloop()
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python region_helper.py <image_path>")
print("Example: python region_helper.py images/cobrai.jpg")
sys.exit(1)
image_path = sys.argv[1]
try:
helper = RegionHelper(image_path)
helper.run()
except FileNotFoundError:
print(f"Error: Image file not found: {image_path}")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
+1 -4
View File
@@ -1,4 +1 @@
Flask>=3.0.0
Werkzeug>=3.0.0
# Pillow>=10.0.0 # Optional - only needed for dynamic image generation
# If you need image generation, install separately: pip install Pillow
Flask==3.1.3
@@ -28,29 +28,26 @@ body {
}
.user-info-bar {
position: absolute;
top: 10px;
right: 20px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 15px;
padding: 2px 10px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
font-size: 14px;
}
.logout-btn {
background-color: #f56565;
color: white;
background: none;
border: none;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
font-weight: 600;
transition: background-color 0.3s;
font-size: 24px;
padding: 5px 10px;
transition: transform 0.2s;
}
.logout-btn:hover {
background-color: #e53e3e;
transform: scale(1.1);
}
.question-container {
+7 -4
View File
@@ -41,12 +41,15 @@ function init() {
// Load question data and other JSON files
function loadQuestionData() {
// Use the data path from the blueprint
const dataPath = '/quiz/data/';
// Load all data files in parallel
Promise.all([
fetch('data/navigation.json').then(r => r.ok ? r.json() : Promise.reject('navigation.json not found')),
fetch('data/products.json').then(r => r.ok ? r.json() : []).catch(() => []),
fetch('data/accessories.json').then(r => r.ok ? r.json() : []).catch(() => []),
fetch('data/product_bitwise.json').then(r => r.ok ? r.json() : []).catch(() => [])
fetch(dataPath + 'navigation.json').then(r => r.ok ? r.json() : Promise.reject('navigation.json not found')),
fetch(dataPath + 'products.json').then(r => r.ok ? r.json() : []).catch(() => []),
fetch(dataPath + 'accessories.json').then(r => r.ok ? r.json() : []).catch(() => []),
fetch(dataPath + 'product_bitwise.json').then(r => r.ok ? r.json() : []).catch(() => [])
])
.then(([questions, products, accessories, bitwise]) => {
questionData = questions;
-77
View File
@@ -1,77 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Page Not Found</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.error-container {
text-align: center;
background-color: white;
padding: 60px 40px;
border: 2px solid #333;
border-radius: 8px;
max-width: 600px;
}
h1 {
font-size: 120px;
color: #333;
margin-bottom: 20px;
}
h2 {
font-size: 32px;
color: #333;
margin-bottom: 15px;
}
p {
font-size: 16px;
color: #666;
margin-bottom: 30px;
line-height: 1.6;
}
.button {
display: inline-block;
padding: 12px 30px;
background-color: #333;
color: white;
text-decoration: none;
border-radius: 4px;
font-size: 16px;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: #555;
}
</style>
</head>
<body>
<div class="error-container">
<h1>404</h1>
<h2>Page Not Found</h2>
<p>Sorry, the page you're looking for doesn't exist or has been moved.</p>
<a href="/" class="button">Go Home</a>
<a href="/quiz" class="button" style="margin-left: 10px;">Start Quiz</a>
</div>
</body>
</html>
-133
View File
@@ -1,133 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Access Denied - CGW Product Finder</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.access-denied-container {
background: white;
padding: 50px;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
text-align: center;
max-width: 500px;
}
.icon {
font-size: 80px;
margin-bottom: 20px;
}
h1 {
color: #f56565;
margin-bottom: 15px;
font-size: 32px;
}
.message {
color: #666;
margin-bottom: 10px;
font-size: 16px;
line-height: 1.6;
}
.permission-info {
background: #fed7d7;
color: #742a2a;
padding: 12px;
border-radius: 5px;
margin: 20px 0;
font-family: 'Courier New', monospace;
font-size: 14px;
border-left: 4px solid #f56565;
}
.btn {
display: inline-block;
padding: 12px 30px;
margin: 10px 5px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
text-decoration: none;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5568d3;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: #e0e0e0;
color: #333;
}
.btn-secondary:hover {
background: #d0d0d0;
transform: translateY(-2px);
}
.contact-info {
margin-top: 30px;
padding-top: 20px;
border-top: 2px solid #e0e0e0;
color: #999;
font-size: 14px;
}
</style>
</head>
<body>
<div class="access-denied-container">
<div class="icon">🚫</div>
<h1>Access Denied</h1>
<p class="message">
You do not have permission to access this page or perform this action.
</p>
{% if required_permission %}
<div class="permission-info">
Required Permission: <strong>{{ required_permission }}</strong>
</div>
{% endif %}
<p class="message">
If you believe this is an error, please contact your administrator.
</p>
<div style="margin-top: 30px;">
<a href="javascript:history.back()" class="btn btn-secondary">← Go Back</a>
<a href="{{ url_for('index') }}" class="btn btn-primary">Return to Home</a>
</div>
<div class="contact-info">
Need help? Contact your system administrator to request access.
</div>
</div>
</body>
</html>
-381
View File
@@ -1,381 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Image Generation - Test Page</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
margin-bottom: 10px;
}
.subtitle {
color: #666;
margin-bottom: 30px;
}
.demo-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-bottom: 40px;
}
.image-container {
border: 2px solid #ddd;
border-radius: 8px;
padding: 20px;
background: #fafafa;
text-align: center;
}
.image-container h3 {
margin-bottom: 15px;
color: #333;
}
.product-image {
max-width: 100%;
height: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: white;
max-height: 500px;
object-fit: contain;
}
.loading {
color: #999;
font-style: italic;
padding: 40px;
}
.controls {
background: #f9f9f9;
padding: 20px;
border-radius: 8px;
margin-bottom: 30px;
}
.control-group {
margin-bottom: 15px;
}
.control-group label {
display: block;
font-weight: bold;
margin-bottom: 5px;
color: #333;
}
.control-group select,
.control-group input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.radio-group {
display: flex;
gap: 15px;
}
.radio-group label {
display: flex;
align-items: center;
gap: 5px;
font-weight: normal;
}
button {
background: #333;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-right: 10px;
}
button:hover {
background: #555;
}
.info-box {
background: #e3f2fd;
border-left: 4px solid #2196F3;
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.info-box h4 {
color: #1976D2;
margin-bottom: 5px;
}
.info-box p {
color: #555;
line-height: 1.6;
}
.url-display {
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
word-break: break-all;
margin-top: 10px;
}
.error {
background: #ffebee;
border-left: 4px solid #f44336;
padding: 15px;
margin: 20px 0;
border-radius: 4px;
color: #c62828;
}
@media (max-width: 768px) {
.demo-section {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<h1>🎨 Dynamic Image Generation API</h1>
<p class="subtitle">Test the product image generation endpoints</p>
<div class="info-box">
<h4>How It Works</h4>
<p>
This demo uses server-side image processing to dynamically generate product images
with different colors and configurations. Select options below to see the image update in real-time.
</p>
</div>
<div class="controls">
<h3>Product Configuration</h3>
<div class="control-group">
<label for="product-select">Product:</label>
<select id="product-select">
<option value="cobrai">COBRAI - Storm Door</option>
</select>
</div>
<div class="control-group">
<label for="color-select">Color:</label>
<select id="color-select">
<option value="white">White</option>
<option value="black">Black</option>
<option value="bronze">Bronze</option>
<option value="sandstone">Sandstone</option>
</select>
</div>
<div class="control-group">
<label>Hinge Location:</label>
<div class="radio-group">
<label>
<input type="radio" name="hinge" value="right" checked>
Right Hinge
</label>
<label>
<input type="radio" name="hinge" value="left">
Left Hinge
</label>
</div>
</div>
<div class="control-group">
<label>
<input type="checkbox" id="cache-checkbox" checked>
Use Cache
</label>
</div>
<button onclick="updateImages()">🔄 Update Images</button>
<button onclick="clearCache()">🗑️ Clear Cache</button>
<button onclick="getConfig()">📋 Get Config</button>
</div>
<div class="demo-section">
<div class="image-container">
<h3>Direct Image URL Method</h3>
<p style="color: #666; font-size: 14px; margin-bottom: 10px;">
Using: <code>&lt;img src="..."&gt;</code>
</p>
<img id="direct-image" class="product-image" src="" alt="Product">
<div class="url-display" id="direct-url">Loading...</div>
</div>
<div class="image-container">
<h3>JSON/Base64 Method</h3>
<p style="color: #666; font-size: 14px; margin-bottom: 10px;">
Using: <code>fetch() + base64</code>
</p>
<img id="json-image" class="product-image" src="" alt="Product">
<div class="url-display" id="json-url">Loading...</div>
</div>
</div>
<div id="error-box" style="display: none;" class="error"></div>
<div id="config-box" style="display: none; margin-top: 20px;">
<h3>Product Configuration</h3>
<pre id="config-display" style="background: #f5f5f5; padding: 15px; border-radius: 4px; overflow-x: auto;"></pre>
</div>
<div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;">
<h3>API Endpoints Used</h3>
<ul style="line-height: 2;">
<li><code>GET /api/product-image/{product}?color={color}&hinge={hinge}</code></li>
<li><code>GET /api/product-image/{product}?color={color}&hinge={hinge}&format=json</code></li>
<li><code>GET /api/product-config/{product}</code></li>
<li><code>POST /api/clear-image-cache</code></li>
</ul>
</div>
</div>
<script>
// Initialize on load
window.addEventListener('DOMContentLoaded', () => {
updateImages();
});
// Auto-update when controls change
document.getElementById('product-select').addEventListener('change', updateImages);
document.getElementById('color-select').addEventListener('change', updateImages);
document.querySelectorAll('[name="hinge"]').forEach(radio => {
radio.addEventListener('change', updateImages);
});
function updateImages() {
const product = document.getElementById('product-select').value;
const color = document.getElementById('color-select').value;
const hinge = document.querySelector('[name="hinge"]:checked').value;
const useCache = document.getElementById('cache-checkbox').checked;
hideError();
// Method 1: Direct image URL
updateDirectImage(product, color, hinge, useCache);
// Method 2: JSON with base64
updateJsonImage(product, color, hinge, useCache);
}
function updateDirectImage(product, color, hinge, useCache) {
const url = `/api/product-image/${product}?color=${color}&hinge=${hinge}&cache=${useCache}`;
const img = document.getElementById('direct-image');
img.src = url;
document.getElementById('direct-url').textContent = url;
}
async function updateJsonImage(product, color, hinge, useCache) {
const url = `/api/product-image/${product}?color=${color}&hinge=${hinge}&format=json&cache=${useCache}`;
try {
const response = await fetch(url);
const data = await response.json();
if (data.status === 'success') {
document.getElementById('json-image').src = data.image;
document.getElementById('json-url').textContent = url;
} else {
showError(`Error: ${data.error || 'Unknown error'}`);
}
} catch (error) {
showError(`Fetch error: ${error.message}`);
}
}
async function getConfig() {
const product = document.getElementById('product-select').value;
const url = `/api/product-config/${product}`;
try {
const response = await fetch(url);
const data = await response.json();
if (data.status === 'success') {
document.getElementById('config-display').textContent =
JSON.stringify(data.config, null, 2);
document.getElementById('config-box').style.display = 'block';
} else {
showError(`Error: ${data.error || 'Unknown error'}`);
}
} catch (error) {
showError(`Fetch error: ${error.message}`);
}
}
async function clearCache() {
const product = document.getElementById('product-select').value;
try {
const response = await fetch('/api/clear-image-cache', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ productCode: product })
});
const data = await response.json();
if (data.status === 'success') {
alert(data.message);
updateImages();
} else {
showError(`Error: ${data.error || 'Unknown error'}`);
}
} catch (error) {
showError(`Fetch error: ${error.message}`);
}
}
function showError(message) {
const errorBox = document.getElementById('error-box');
errorBox.textContent = message;
errorBox.style.display = 'block';
}
function hideError() {
document.getElementById('error-box').style.display = 'none';
}
</script>
</body>
</html>
-230
View File
@@ -1,230 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Details Form</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: white;
padding: 20px;
border: 2px solid #333;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
font-size: 14px;
}
input[type="text"],
input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #333;
font-size: 14px;
}
textarea {
width: 100%;
padding: 8px;
border: 1px solid #333;
font-size: 14px;
resize: vertical;
min-height: 80px;
}
button {
width: 100%;
padding: 12px;
background-color: #d0d0ff;
border: 1px solid #333;
cursor: pointer;
font-size: 14px;
font-weight: bold;
margin-bottom: 15px;
}
button:hover {
background-color: #b0b0ff;
}
.specifications-section {
border: 3px solid #4CAF50;
padding: 15px;
margin-bottom: 15px;
background-color: #f0fff0;
}
.specifications-section.hidden {
display: none;
}
.conditional-field {
display: none;
}
.conditional-field.visible {
display: block;
}
select {
width: 100%;
padding: 8px;
border: 1px solid #333;
font-size: 14px;
}
.spec-row {
display: grid;
grid-template-columns: 120px 1fr;
gap: 10px;
margin-bottom: 10px;
align-items: center;
}
.spec-row label {
margin-bottom: 0;
}
.spec-row input {
border: 1px solid #333;
padding: 6px;
}
.questions-section {
border: 1px solid #333;
padding: 15px;
text-align: center;
background-color: #fafafa;
}
.questions-section p {
margin-bottom: 10px;
font-size: 12px;
}
.questions-section .placeholder {
font-style: italic;
color: #666;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="form-group">
<label>Type (door, window, other)</label>
<select id="typeSelect" onchange="toggleOtherField()">
<option value="">-- Select Type --</option>
<option value="door">Door</option>
<option value="window">Window</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group conditional-field" id="otherField">
<label>Please specify</label>
<input type="text" placeholder="Enter type details">
</div>
<div class="form-group">
<label>Description</label>
<textarea placeholder="textfield"></textarea>
</div>
<div class="form-group">
<label>Notes</label>
<textarea placeholder="textfield"></textarea>
</div>
<button onclick="toggleSpecifications()">Match and Review</button>
<div class="specifications-section hidden" id="specificationsSection">
<div class="spec-row">
<label>Product Code:</label>
<input type="text" placeholder="" readonly>
</div>
<div class="spec-row">
<label>Width:</label>
<input type="text" placeholder="">
</div>
<div class="spec-row">
<label>Height</label>
<input type="text" placeholder="">
</div>
<div class="spec-row">
<label>Color</label>
<input type="text" placeholder="">
</div>
<div class="spec-row">
<label>Frame:</label>
<input type="text" placeholder="">
</div>
<div class="spec-row">
<label>Screen:</label>
<input type="text" placeholder="">
</div>
<div class="spec-row">
<label>Etc...</label>
<input type="text" placeholder="">
</div>
</div>
<div class="form-group">
<label>Quantity</label>
<input type="number" min="1" value="1" placeholder="">
</div>
<button>Confirm and Add</button>
<div class="questions-section">
<p>Possible questions for customers based on what is selected or missing</p>
<div class="placeholder">[list - checkbox per question]</div>
</div>
</div>
<script>
function toggleSpecifications() {
const section = document.getElementById('specificationsSection');
section.classList.toggle('hidden');
}
function toggleOtherField() {
const typeSelect = document.getElementById('typeSelect');
const otherField = document.getElementById('otherField');
if (typeSelect.value === 'other') {
otherField.classList.add('visible');
} else {
otherField.classList.remove('visible');
}
}
</script>
</body>
</html>
-75
View File
@@ -1,75 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Finder</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="container">
<div class="header">
<h1>Product Finder</h1>
<div class="user-info-bar" id="userInfoBar">
<span id="userLocationInfo"></span>
<button onclick="logout()" class="logout-btn">Logout</button>
</div>
</div>
<div class="breadcrumb" id="breadcrumb">
Start
</div>
<div id="content">
<!-- Content will be dynamically loaded here -->
</div>
</div>
<script>
// Base URL for API calls (supports subdirectory deployments)
const BASE_URL = '{{ base_url }}';
// Load user session info
async function loadUserInfo() {
try {
const response = await fetch(BASE_URL + '/api/session');
const data = await response.json();
if (data.status === 'success') {
const locationNames = {
'LINDS': 'Lindsborg',
'IOLA': 'Iola',
'KC': 'KC',
'BMD': 'BMD'
};
const currentLoc = locationNames[data.currentLocation] || data.currentLocation;
document.getElementById('userLocationInfo').textContent =
`👤 ${data.username} | 📍 ${currentLoc}`;
}
} catch (error) {
console.error('Error loading user info:', error);
}
}
async function logout() {
if (confirm('Are you sure you want to log out?')) {
try {
await fetch(BASE_URL + '/api/logout', { method: 'POST' });
window.location.href = BASE_URL + '/login?message=' + encodeURIComponent('Successfully logged out');
} catch (error) {
window.location.href = BASE_URL + '/login';
}
}
}
// Load user info when page loads
loadUserInfo();
</script>
<script>
// Pass BASE_URL to script.js by setting it as a window variable
window.APP_BASE_URL = BASE_URL;
</script>
<script src="{{ url_for('serve_js', filename='script.js') }}"></script>
</body>
</html>
+7 -49
View File
@@ -3,14 +3,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - CGW Product Finder</title>
<title>Login</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@@ -113,27 +109,6 @@
border-left: 4px solid #f56565;
}
.alert-info {
background: #bee3f8;
color: #2c5282;
border-left: 4px solid #4299e1;
}
.footer-links {
text-align: center;
margin-top: 20px;
font-size: 14px;
}
.footer-links a {
color: #667eea;
text-decoration: none;
}
.footer-links a:hover {
text-decoration: underline;
}
.loading-spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
@@ -156,7 +131,7 @@
<body>
<div class="login-container">
<div class="login-header">
<h1>🔐 CGW Product Finder</h1>
<h1>🔐 Login</h1>
<p>Please sign in to continue</p>
</div>
@@ -180,16 +155,9 @@
<span class="loading-spinner" id="loadingSpinner"></span>
</button>
</form>
<div class="footer-links">
<a href="{{ url_for('user_manager') }}">User Management</a>
</div>
</div>
<script>
// Base URL for API calls (supports subdirectory deployments)
const BASE_URL = '{{ base_url }}';
document.getElementById('loginForm').addEventListener('submit', async (e) => {
e.preventDefault();
@@ -198,12 +166,11 @@
const loginBtn = document.getElementById('loginBtn');
const spinner = document.getElementById('loadingSpinner');
// Disable button and show spinner
loginBtn.disabled = true;
spinner.style.display = 'inline-block';
try {
const response = await fetch(BASE_URL + '/api/login', {
const response = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -216,11 +183,9 @@
if (data.status === 'success') {
// Check if user needs to select a location
if (data.requiresLocationSelection) {
// Redirect to location selection page
window.location.href = '/select-location';
window.location.href = '{{ url_for("auth.select_location_page") }}';
} else {
// Redirect to main app
window.location.href = '/';
window.location.href = '{{ url_for("products.product_finder") }}';
}
} else {
showAlert(data.message || 'Invalid username or password');
@@ -243,13 +208,6 @@
alert.classList.remove('show');
}, 5000);
}
// Check if there's a message in URL (e.g., after logout)
const urlParams = new URLSearchParams(window.location.search);
const message = urlParams.get('message');
if (message) {
showAlert(message);
}
</script>
</body>
</html>
+84
View File
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>Product Finder</title>
<link rel="stylesheet" href="{{ url_for('products.serve_css', filename='styles.css') }}">
</head>
<body>
<div class="container">
<div class="header">
<h1>Product Finder</h1>
</div>
<div class="user-info-bar" id="userInfoBar">
<span id="userLocationInfo"></span>
<a href="{{ url_for('auth.logout') }}" class="logout-btn" title="Logout"
onclick="return confirm('Are you sure you want to log out?');"
style="background: none; border: none; cursor: pointer; font-size: 16px; text-decoration: none; display: inline-block; padding: 8px 12px;">🚪</a>
</div>
<div class="breadcrumb" id="breadcrumb">
Start
</div>
<div id="content">
<!-- Content will be dynamically loaded here -->
</div>
</div>
<script>
// Base URL for API calls
const BASE_URL = '';
// Load user session info
async function loadUserInfo() {
try {
const response = await fetch('/api/session');
const data = await response.json();
if (data.status === 'success') {
const locationNames = {
'LINDS': 'Lindsborg',
'IOLA': 'Iola',
'KC': 'Kansas City',
'BMD': 'BMD'
};
const currentLoc = locationNames[data.currentLocation] || data.currentLocation;
const canChangeLocation = data.accessibleLocations && data.accessibleLocations.length > 1;
let locationDisplay;
if (canChangeLocation) {
locationDisplay = `<a href="{{ url_for('auth.select_location_page') }}" style="color: #6a4c93; text-decoration: none; font-weight: 500; cursor: pointer;"
onmouseover="this.style.textDecoration='underline'"
onmouseout="this.style.textDecoration='none'"
title="Click to change location">📍 ${currentLoc}</a>`;
} else {
locationDisplay = `📍 ${currentLoc}`;
}
document.getElementById('userLocationInfo').innerHTML =
`👤 ${data.username} | ${locationDisplay}`;
}
} catch (error) {
console.error('Error loading user info:', error);
}
}
// Load user info when page loads
loadUserInfo();
</script>
<script>
// Pass BASE_URL to script.js by setting it as a window variable
window.APP_BASE_URL = '';
// Set data path for the quiz
window.DATA_PATH = '{{ url_for("products.serve_data", filename="") }}';
</script>
<script src="{{ url_for('products.serve_js', filename='script.js') }}"></script>
</body>
</html>
+201 -185
View File
@@ -3,14 +3,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Select Location - CGW Product Finder</title>
<title>Select Location</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@@ -43,72 +39,75 @@
.location-header p {
color: #666;
font-size: 14px;
font-size: 15px;
}
.user-info {
background: #f7fafc;
padding: 15px;
border-radius: 5px;
margin-bottom: 25px;
margin-bottom: 30px;
border-left: 4px solid #667eea;
}
.user-info p {
.user-info strong {
color: #333;
display: block;
margin-bottom: 5px;
}
.user-info strong {
color: #667eea;
.user-info span {
color: #666;
font-size: 14px;
}
.location-list {
margin-bottom: 25px;
.location-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
margin-bottom: 20px;
}
.location-item {
.location-card {
background: #f7fafc;
padding: 15px 20px;
border-radius: 5px;
margin-bottom: 10px;
border: 3px solid #e0e0e0;
border-radius: 8px;
padding: 30px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
border: 2px solid transparent;
display: flex;
align-items: center;
position: relative;
}
.location-item:hover {
background: #e6f2ff;
.location-card:hover {
border-color: #667eea;
transform: translateX(5px);
background: #edf2f7;
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
}
.location-item input[type="radio"] {
margin-right: 15px;
width: 20px;
height: 20px;
cursor: pointer;
}
.location-item label {
cursor: pointer;
flex: 1;
font-size: 16px;
color: #333;
font-weight: 500;
}
.location-badge {
background: #667eea;
.location-card.selected {
border-color: #667eea;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
}
.location-card .icon {
font-size: 40px;
margin-bottom: 10px;
}
.location-card .name {
font-size: 18px;
font-weight: 600;
}
.location-card .description {
font-size: 13px;
margin-top: 5px;
opacity: 0.8;
}
.btn {
width: 100%;
padding: 14px;
@@ -134,30 +133,6 @@
transform: none;
}
.btn-logout {
background: #f56565;
margin-top: 15px;
}
.btn-logout:hover {
background: #e53e3e;
box-shadow: 0 5px 15px rgba(245, 101, 101, 0.4);
}
.btn-admin {
background: #48bb78;
margin-top: 15px;
}
.btn-admin:hover {
background: #38a169;
box-shadow: 0 5px 15px rgba(72, 187, 120, 0.4);
}
.btn-admin.hidden {
display: none;
}
.alert {
padding: 12px;
border-radius: 5px;
@@ -174,145 +149,194 @@
color: #742a2a;
border-left: 4px solid #f56565;
}
.footer {
text-align: center;
margin-top: 20px;
}
.footer a {
color: #667eea;
text-decoration: none;
font-size: 14px;
}
.footer a:hover {
text-decoration: underline;
}
.loading-spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
display: inline-block;
margin-left: 10px;
vertical-align: middle;
display: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (max-width: 600px) {
.location-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="location-container">
<div class="location-header">
<h1>📍 Select Your Location</h1>
<p>Choose a location to access the Product Finder</p>
<p>Choose which location you'll be working from today</p>
</div>
<div class="user-info" id="userInfo">
<p><strong>Welcome:</strong> <span id="userName"></span></p>
<p><strong>Default Location:</strong> <span id="defaultLocation"></span></p>
<div class="user-info">
<strong>Welcome, <span id="username">User</span>!</strong>
<span>Default Location: <span id="defaultLocation">-</span></span>
</div>
<div class="alert alert-error" id="errorAlert"></div>
<form id="locationForm">
<div class="location-list" id="locationList">
<!-- Locations will be populated here -->
</div>
<div class="location-grid" id="locationGrid">
<!-- Locations will be populated here -->
</div>
<button type="submit" class="btn" id="continueBtn">
Continue to Product Finder
</button>
</form>
<button class="btn btn-admin hidden" id="userManagementBtn" onclick="goToUserManagement()">
⚙️ User Management
<button class="btn" id="confirmBtn" disabled>
Confirm Location
<span class="loading-spinner" id="loadingSpinner"></span>
</button>
<button class="btn btn-logout" onclick="logout()">
Sign Out
</button>
<div class="footer">
<a href="{{ url_for('users.user_manager') }}" id="manageUsersLink" style="display: none; margin-right: 15px;">Manage Users</a>
<a href="{{ url_for('auth.logout') }}">Logout</a>
</div>
</div>
<script>
// Base URL for API calls (supports subdirectory deployments)
const BASE_URL = '{{ base_url }}';
const LOCATION_NAMES = {
'LINDS': 'Lindsborg',
'IOLA': 'Iola',
'KC': 'KC',
'BMD': 'BMD'
};
let selectedLocation = null;
let sessionData = null;
async function loadLocationData() {
// Location details
const locationDetails = {
'LINDS': {
icon: '🏭',
name: 'LINDS',
description: 'Lindsborg Location'
},
'IOLA': {
icon: '🏢',
name: 'IOLA',
description: 'Iola Location'
},
'KC': {
icon: '🌆',
name: 'KC',
description: 'Kansas City Location'
},
'BMD': {
icon: '🏛️',
name: 'BMD',
description: 'BMD Location'
}
};
// Load session data on page load
loadSessionData();
async function loadSessionData() {
try {
const response = await fetch(BASE_URL + '/api/session');
const response = await fetch('/api/session');
const data = await response.json();
if (data.status === 'success') {
sessionData = data;
// Populate user info
document.getElementById('userName').textContent = data.username;
document.getElementById('defaultLocation').textContent =
LOCATION_NAMES[data.defaultLocation] || data.defaultLocation;
document.getElementById('username').textContent = data.username;
document.getElementById('defaultLocation').textContent = data.defaultLocation || 'Not set';
// Populate location list
const locationList = document.getElementById('locationList');
const locations = data.accessibleLocations || [];
if (locations.length === 0) {
showAlert('No accessible locations found. Please contact an administrator.');
document.getElementById('continueBtn').disabled = true;
return;
// Show manage users link if user has permission
if (data.permissions && data.permissions.manage_users === true) {
document.getElementById('manageUsersLink').style.display = 'inline';
}
locationList.innerHTML = locations.map((code, index) => {
const isDefault = code === data.defaultLocation;
const checked = isDefault ? 'checked' : '';
return `
<div class="location-item" onclick="selectLocation('${code}')">
<input type="radio" name="location" value="${code}"
id="loc_${code}" ${checked}>
<label for="loc_${code}">
${LOCATION_NAMES[code] || code}
</label>
${isDefault ? '<span class="location-badge">Default</span>' : ''}
</div>
`;
}).join('');
// Render accessible locations
renderLocations(data.accessibleLocations || []);
// Auto-select default location if available
if (data.defaultLocation && data.accessibleLocations.includes(data.defaultLocation)) {
selectLocation(data.defaultLocation);
}
} else {
// Not logged in or session expired
window.location.href = BASE_URL + '/login?message=' + encodeURIComponent('Please log in first');
showError('Error loading session. Please login again.');
setTimeout(() => {
window.location.href = '{{ url_for("auth.login_page") }}';
}, 2000);
}
// Check if user has manage_users permission
await checkUserManagementPermission();
} catch (error) {
showAlert('Error loading location data. Please try again.');
showError('Error connecting to server.');
}
}
async function checkUserManagementPermission() {
try {
const response = await fetch(BASE_URL + '/api/check-permission', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ permission: 'manage_users' })
});
function renderLocations(accessibleLocations) {
const grid = document.getElementById('locationGrid');
const data = await response.json();
if (data.status === 'success' && data.hasPermission) {
document.getElementById('userManagementBtn').classList.remove('hidden');
}
} catch (error) {
// Permission check failed, keep button hidden
console.error('Error checking permission:', error);
}
}
function goToUserManagement() {
window.location.href = BASE_URL + '/users';
}
function selectLocation(code) {
document.getElementById(`loc_${code}`).checked = true;
}
document.getElementById('locationForm').addEventListener('submit', async (e) => {
e.preventDefault();
const selectedLocation = document.querySelector('input[name="location"]:checked')?.value;
if (!selectedLocation) {
showAlert('Please select a location');
if (accessibleLocations.length === 0) {
grid.innerHTML = '<p style="color: #666; text-align: center; grid-column: 1 / -1;">No accessible locations found.</p>';
return;
}
grid.innerHTML = accessibleLocations.map(locCode => {
const loc = locationDetails[locCode] || {
icon: '📍',
name: locCode,
description: locCode
};
return `
<div class="location-card" onclick="selectLocation('${locCode}')" data-location="${locCode}">
<div class="icon">${loc.icon}</div>
<div class="name">${loc.name}</div>
<div class="description">${loc.description}</div>
</div>
`;
}).join('');
}
function selectLocation(locCode) {
selectedLocation = locCode;
// Remove selected class from all cards
document.querySelectorAll('.location-card').forEach(card => {
card.classList.remove('selected');
});
// Add selected class to clicked card
const card = document.querySelector(`[data-location="${locCode}"]`);
if (card) {
card.classList.add('selected');
}
// Enable confirm button
document.getElementById('confirmBtn').disabled = false;
}
document.getElementById('confirmBtn').addEventListener('click', async () => {
if (!selectedLocation) return;
const confirmBtn = document.getElementById('confirmBtn');
const spinner = document.getElementById('loadingSpinner');
confirmBtn.disabled = true;
spinner.style.display = 'inline-block';
try {
const response = await fetch(BASE_URL + '/api/select-location', {
const response = await fetch('/api/select-location', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -323,26 +347,21 @@
const data = await response.json();
if (data.status === 'success') {
// Redirect to main app
window.location.href = BASE_URL + '/';
// Redirect to quiz page
window.location.href = '{{ url_for("products.product_finder") }}';
} else {
showAlert(data.message || 'Error selecting location');
showError(data.message || 'Error selecting location');
confirmBtn.disabled = false;
spinner.style.display = 'none';
}
} catch (error) {
showAlert('Error connecting to server. Please try again.');
showError('Error connecting to server');
confirmBtn.disabled = false;
spinner.style.display = 'none';
}
});
async function logout() {
try {
await fetch(BASE_URL + '/api/logout', { method: 'POST' });
window.location.href = BASE_URL + '/login?message=' + encodeURIComponent('Successfully logged out');
} catch (error) {
window.location.href = BASE_URL + '/login';
}
}
function showAlert(message) {
function showError(message) {
const alert = document.getElementById('errorAlert');
alert.textContent = message;
alert.classList.add('show');
@@ -351,9 +370,6 @@
alert.classList.remove('show');
}, 5000);
}
// Load location data on page load
loadLocationData();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
-228
View File
@@ -1,228 +0,0 @@
#!/usr/bin/env python3
"""
Comprehensive app test script
Run this through control panel to diagnose issues
Writes detailed logs to test_app.log
"""
import sys
import os
from datetime import datetime
# Setup logging
log_file = os.path.join(os.path.dirname(__file__), 'test_app.log')
def log(message, also_print=True):
"""Write to log file and optionally print"""
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
full_message = f"[{timestamp}] {message}"
with open(log_file, 'a') as f:
f.write(full_message + '\n')
if also_print:
print(full_message)
try:
log("="*70)
log("APP TEST SCRIPT - START")
log("="*70)
# 1. Environment Info
log("\n1. PYTHON ENVIRONMENT")
log(f" Python: {sys.version}")
log(f" Executable: {sys.executable}")
log(f" CWD: {os.getcwd()}")
# 2. Check environment variables
log("\n2. ENVIRONMENT VARIABLES")
log(f" APPLICATION_ROOT: {os.environ.get('APPLICATION_ROOT', 'NOT SET')}")
log(f" FLASK_ENV: {os.environ.get('FLASK_ENV', 'NOT SET')}")
log(f" SECRET_KEY: {'SET' if os.environ.get('SECRET_KEY') else 'NOT SET'}")
# 3. Check critical files
log("\n3. FILE STRUCTURE CHECK")
files_to_check = [
'app.py',
'passenger_wsgi.py',
'config.py',
'data/users.json',
'templates/login.html',
'templates/index2.html',
'templates/select_location.html',
'templates/user_manager.html'
]
all_files_exist = True
for file_path in files_to_check:
full_path = os.path.join(os.path.dirname(__file__), file_path)
exists = os.path.exists(full_path)
status = "" if exists else "✗ MISSING"
log(f" {status} {file_path}")
if not exists:
all_files_exist = False
if not all_files_exist:
log("\n⚠️ CRITICAL: Missing files detected!")
# 4. Check dependencies
log("\n4. PYTHON PACKAGES")
packages = [
('flask', 'Flask'),
('werkzeug', 'Werkzeug')
]
all_packages_ok = True
for module_name, display_name in packages:
try:
module = __import__(module_name)
try:
from importlib.metadata import version
ver = version(module_name)
except:
ver = getattr(module, '__version__', 'unknown')
log(f"{display_name}: {ver}")
except ImportError as e:
log(f"{display_name}: NOT INSTALLED ({e})")
all_packages_ok = False
if not all_packages_ok:
log("\n⚠️ CRITICAL: Missing packages! Run: pip install Flask==3.0.0 Werkzeug==3.0.1")
sys.exit(1)
# 5. Try importing app
log("\n5. APP IMPORT TEST")
log(" Attempting to import Flask app...")
try:
# Make sure current directory is in path
current_dir = os.path.dirname(__file__)
if current_dir not in sys.path:
sys.path.insert(0, current_dir)
from app import app
log(" ✓ Flask app imported successfully!")
# Check app config
log("\n6. APP CONFIGURATION")
log(f" APPLICATION_ROOT: {app.config.get('APPLICATION_ROOT', 'NOT SET')}")
log(f" DEBUG: {app.config.get('DEBUG')}")
log(f" SECRET_KEY: {'SET (' + str(len(app.config.get('SECRET_KEY', ''))) + ' chars)' if app.config.get('SECRET_KEY') else 'NOT SET'}")
# Check if middleware applied
log(f" WSGI App Type: {type(app.wsgi_app).__name__}")
if 'PrefixMiddleware' in str(type(app.wsgi_app)):
log(" ✓ PrefixMiddleware is active")
else:
log(" ⚠️ PrefixMiddleware NOT active (may cause issues at /product-finder)")
# Count routes
log("\n7. ROUTES CHECK")
routes = list(app.url_map.iter_rules())
log(f" Total routes: {len(routes)}")
# Check critical routes
critical_routes = ['/login', '/api/login', '/users', '/select-location']
log(" Critical routes:")
for route_path in critical_routes:
found = any(str(rule) == route_path or str(rule).startswith(route_path + '<') for rule in routes)
status = "" if found else "✗ MISSING"
log(f" {status} {route_path}")
# 8. Test loading users
log("\n8. USER DATA TEST")
try:
users_file = os.path.join(current_dir, 'data', 'users.json')
if os.path.exists(users_file):
import json
with open(users_file, 'r') as f:
users = json.load(f)
log(f" ✓ Users file loaded: {len(users)} users")
log(f" Usernames: {', '.join([u.get('username', '?') for u in users])}")
else:
log(f" ✗ Users file NOT FOUND at {users_file}")
except Exception as e:
log(f" ✗ Error loading users: {e}")
# 9. Test a simple request
log("\n9. REQUEST TEST")
log(" Testing if app can handle requests...")
with app.test_client() as client:
# Test root redirect
try:
response = client.get('/')
log(f" GET / -> Status: {response.status_code}")
if response.status_code == 302:
log(f" Redirects to: {response.location}")
except Exception as e:
log(f" ✗ Error testing /: {e}")
# Test login page
try:
response = client.get('/login')
log(f" GET /login -> Status: {response.status_code}")
if response.status_code != 200:
log(f" ⚠️ Login page returned {response.status_code} instead of 200")
except Exception as e:
log(f" ✗ Error testing /login: {e}")
# 10. Summary
log("\n" + "="*70)
log("TEST SUMMARY")
log("="*70)
if all_files_exist and all_packages_ok:
log("✓ All files present")
log("✓ All packages installed")
log("✓ App imports successfully")
log(f"{len(routes)} routes registered")
app_root = app.config.get('APPLICATION_ROOT', '/')
if app_root == '/product-finder':
log("✓ Configured for /product-finder deployment")
else:
log(f"⚠️ APPLICATION_ROOT is '{app_root}' (should be '/product-finder' for production)")
log("\n🎉 APP APPEARS READY!")
log("\nIf still getting 500 errors:")
log("1. Check that data/users.json exists")
log("2. Verify APPLICATION_ROOT env var is set to /product-finder")
log("3. Check Apache error log for runtime errors")
log("4. Ensure .htaccess is correct")
else:
log("\n⚠️ ISSUES FOUND - Fix these before deployment")
log("="*70)
log(f"\nLog saved to: {log_file}")
except ImportError as e:
log(f" ✗ FAILED to import app!")
log(f" Error: {e}")
import traceback
log("\nFull traceback:")
log(traceback.format_exc())
log("\n❌ CRITICAL ERROR: Cannot import Flask app")
log("Check that app.py exists and has no syntax errors")
except Exception as e:
log(f" ✗ Unexpected error during import!")
log(f" Error: {e}")
import traceback
log("\nFull traceback:")
log(traceback.format_exc())
except Exception as e:
log(f"\n❌ FATAL ERROR: {e}")
import traceback
log(traceback.format_exc())
finally:
log("\n" + "="*70)
log("TEST COMPLETE")
log("="*70)
print(f"\n📄 Full log saved to: {log_file}")
print("Download this file to see all test results")
-171
View File
@@ -1,171 +0,0 @@
"""
Deployment diagnostic script for /product-finder
Run this on the server to verify configuration
"""
import os
import sys
print("=" * 70)
print("CGW PRODUCT FINDER - DEPLOYMENT DIAGNOSTIC")
print("=" * 70)
print()
# Check Python version
print("📌 Python Environment:")
print(f" Version: {sys.version}")
print(f" Executable: {sys.executable}")
print(f" Current Directory: {os.getcwd()}")
print()
# Check environment variable
print("📌 Environment Variables:")
app_root_env = os.environ.get('APPLICATION_ROOT')
if app_root_env:
print(f" APPLICATION_ROOT: {app_root_env}")
else:
print(f" APPLICATION_ROOT: NOT SET ⚠️")
print(f" Setting temporarily for test: /product-finder")
os.environ['APPLICATION_ROOT'] = '/product-finder'
print()
# Try importing Flask
print("📌 Flask Installation:")
try:
import flask
print(f" Flask version: {flask.__version__}")
except ImportError as e:
print(f" ✗ Flask not installed: {e}")
sys.exit(1)
# Try importing app
print()
print("📌 Application Import:")
try:
from app import app
print(f" ✓ App imported successfully")
except Exception as e:
print(f" ✗ Error importing app:")
print(f" {e}")
import traceback
traceback.print_exc()
sys.exit(1)
# Check app configuration
print()
print("📌 Application Configuration:")
print(f" APPLICATION_ROOT: {app.config.get('APPLICATION_ROOT')}")
print(f" SECRET_KEY set: {'Yes' if app.config.get('SECRET_KEY') else 'No'}")
print(f" DEBUG mode: {app.config.get('DEBUG')}")
print(f" ENV: {app.config.get('ENV', 'not set')}")
print()
# Check middleware
print("📌 WSGI Middleware:")
wsgi_app_type = type(app.wsgi_app).__name__
if 'PrefixMiddleware' in str(type(app.wsgi_app)):
print(f" ✓ PrefixMiddleware applied")
print(f" Type: {wsgi_app_type}")
elif wsgi_app_type == 'Flask':
print(f" ⚠️ No middleware applied (running at root)")
print(f" Type: {wsgi_app_type}")
else:
print(f" Middleware type: {wsgi_app_type}")
print()
# Check routes
print("📌 Registered Routes:")
routes_count = len(list(app.url_map.iter_rules()))
print(f" Total routes: {routes_count}")
# Check critical routes
critical_routes = ['/login', '/api/login', '/users', '/api/session']
print(f" Critical routes:")
for route in critical_routes:
found = any(str(rule) == route for rule in app.url_map.iter_rules())
status = "" if found else ""
print(f" {status} {route}")
print()
# Check file structure
print("📌 File Structure:")
critical_files = [
'app.py',
'passenger_wsgi.py',
'config.py',
'templates/login.html',
'templates/index2.html',
'data/users.json'
]
for file_path in critical_files:
exists = os.path.exists(file_path)
status = "" if exists else ""
print(f" {status} {file_path}")
print()
# Check dependencies
print("📌 Python Dependencies:")
deps = [
('werkzeug', 'Werkzeug'),
('flask', 'Flask'),
]
try:
from PIL import Image
deps.append(('PIL', 'Pillow'))
except ImportError:
pass
for module_name, display_name in deps:
try:
module = __import__(module_name)
version = getattr(module, '__version__', 'unknown')
print(f"{display_name}: {version}")
except ImportError:
print(f"{display_name}: NOT INSTALLED")
print()
# Summary
print("=" * 70)
print("DEPLOYMENT STATUS")
print("=" * 70)
issues = []
if not os.environ.get('APPLICATION_ROOT'):
issues.append("APPLICATION_ROOT not set in environment")
if app.config.get('APPLICATION_ROOT') == '/':
issues.append("APPLICATION_ROOT is '/' but should be '/product-finder' for production")
if not os.path.exists('templates/login.html'):
issues.append("Template files missing")
if not os.path.exists('data/users.json'):
issues.append("User data file missing")
if issues:
print()
print("⚠️ ISSUES FOUND:")
for issue in issues:
print(f" - {issue}")
print()
print("📝 NEXT STEPS:")
print(" 1. Upload missing files to server")
print(" 2. Set APPLICATION_ROOT environment variable")
print(" 3. Restart Passenger: touch tmp/restart.txt")
print(" 4. Check error logs for details")
else:
print()
print("✓ All checks passed!")
print()
print("🚀 DEPLOYMENT READY")
print()
print("To restart Passenger:")
print(" mkdir -p tmp && touch tmp/restart.txt")
print()
print("To test:")
print(" https://columbiawindows.com/product-finder/")
print()
print("=" * 70)
-86
View File
@@ -1,86 +0,0 @@
"""
Quick test to verify Flask routes are registered correctly
Run this from the app folder: python test_routes.py
"""
import sys
import os
# Add current directory to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
from app import app
print("=" * 60)
print("FLASK ROUTES TEST")
print("=" * 60)
print()
print("✓ Flask app imported successfully")
print()
print("Registered routes:")
print("-" * 60)
routes = []
for rule in app.url_map.iter_rules():
routes.append({
'endpoint': rule.endpoint,
'methods': ', '.join(sorted(rule.methods - {'HEAD', 'OPTIONS'})),
'path': str(rule)
})
# Sort by path
routes.sort(key=lambda x: x['path'])
# Find all login-related routes
login_routes = [r for r in routes if 'login' in r['path'].lower() or 'login' in r['endpoint'].lower()]
user_routes = [r for r in routes if 'user' in r['path'].lower()]
print("\n📝 Login & Authentication Routes:")
for route in login_routes:
print(f" {route['path']:40} [{route['methods']:15}] -> {route['endpoint']}")
print("\n👥 User Management Routes:")
for route in user_routes:
print(f" {route['path']:40} [{route['methods']:15}] -> {route['endpoint']}")
print("\n📊 Total routes registered:", len(routes))
print()
print("=" * 60)
print("✓ All routes loaded successfully!")
print("=" * 60)
print()
print("To start the server:")
print(" python app.py")
print()
print("Then access:")
print(" http://localhost:8080/login")
print(" http://localhost:8080/users")
print()
except ImportError as e:
print("=" * 60)
print("❌ IMPORT ERROR")
print("=" * 60)
print()
print(f"Failed to import Flask app: {e}")
print()
print("This might be because:")
print(" 1. Flask is not installed: pip install Flask")
print(" 2. Werkzeug is not installed: pip install Werkzeug")
print(" 3. There's a syntax error in app.py")
print()
print("Try running:")
print(" pip install -r requirements.txt")
print()
except Exception as e:
print("=" * 60)
print("❌ ERROR")
print("=" * 60)
print()
print(f"Error: {e}")
print()
import traceback
traceback.print_exc()
print()
-142
View File
@@ -1,142 +0,0 @@
#!/usr/bin/env python3
"""
Server troubleshooting script for 403/404 errors
Run this on the server to diagnose Apache/Passenger issues
"""
import os
import sys
print("=" * 70)
print("TROUBLESHOOTING 403/404 ERRORS")
print("=" * 70)
print()
# Check current directory
current_dir = os.getcwd()
print(f"📁 Current directory: {current_dir}")
print()
# Check file permissions
print("📌 File Permissions Check:")
files_to_check = [
'passenger_wsgi.py',
'.htaccess',
'app.py',
'data/users.json',
'templates/login.html'
]
for file in files_to_check:
if os.path.exists(file):
stat_info = os.stat(file)
perms = oct(stat_info.st_mode)[-3:]
print(f"{file:<30} Permissions: {perms}")
else:
print(f"{file:<30} NOT FOUND")
print()
# Check directory permissions
print("📌 Directory Permissions:")
dirs_to_check = ['.', 'templates', 'data', 'static', 'tmp']
for dir_path in dirs_to_check:
if os.path.exists(dir_path):
stat_info = os.stat(dir_path)
perms = oct(stat_info.st_mode)[-3:]
print(f"{dir_path:<30} Permissions: {perms}")
else:
print(f" ⚠️ {dir_path:<30} NOT FOUND (might be OK)")
print()
# Check for tmp/restart.txt
print("📌 Passenger Restart Check:")
if os.path.exists('tmp/restart.txt'):
from datetime import datetime
mtime = os.path.getmtime('tmp/restart.txt')
mtime_str = datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
print(f" ✓ tmp/restart.txt exists (last modified: {mtime_str})")
else:
print(f" ✗ tmp/restart.txt NOT FOUND")
print(f" Create it with: mkdir -p tmp && touch tmp/restart.txt")
print()
# Check environment variables
print("📌 Environment Variables:")
print(f" APPLICATION_ROOT: {os.environ.get('APPLICATION_ROOT', 'NOT SET')}")
print(f" HOME: {os.environ.get('HOME', 'NOT SET')}")
print(f" USER: {os.environ.get('USER', 'NOT SET')}")
print()
# Check .htaccess content
print("📌 .htaccess Configuration:")
if os.path.exists('.htaccess'):
print(f" ✓ .htaccess exists")
with open('.htaccess', 'r') as f:
content = f.read()
if 'PassengerEnabled' in content:
print(f" ✓ PassengerEnabled directive found")
else:
print(f" ✗ PassengerEnabled directive NOT FOUND")
if 'PassengerAppRoot' in content:
print(f" ✓ PassengerAppRoot directive found")
# Extract the path
for line in content.split('\n'):
if 'PassengerAppRoot' in line:
print(f" Value: {line.strip()}")
else:
print(f" ✗ PassengerAppRoot NOT FOUND")
if 'PassengerPython' in content:
print(f" ✓ PassengerPython directive found")
for line in content.split('\n'):
if 'PassengerPython' in line:
print(f" Value: {line.strip()}")
python_path = line.split()[-1] if len(line.split()) > 1 else ''
if os.path.exists(python_path):
print(f" ✓ Python executable exists")
else:
print(f" ✗ Python executable NOT FOUND at {python_path}")
else:
print(f" ✗ .htaccess NOT FOUND")
print()
# Try importing Flask
print("📌 Flask Import Test:")
try:
sys.path.insert(0, current_dir)
from app import app
print(f" ✓ Flask app imported successfully")
print(f" Routes registered: {len(list(app.url_map.iter_rules()))}")
except Exception as e:
print(f" ✗ Error importing app: {e}")
print()
# Recommendations
print("=" * 70)
print("COMMON FIXES FOR 403/404 ERRORS:")
print("=" * 70)
print()
print("1️⃣ RESTART PASSENGER:")
print(" mkdir -p tmp")
print(" touch tmp/restart.txt")
print()
print("2️⃣ CHECK FILE PERMISSIONS:")
print(" chmod 644 passenger_wsgi.py")
print(" chmod 644 .htaccess")
print(" chmod 755 .")
print()
print("3️⃣ VERIFY PATHS IN .htaccess:")
print(" PassengerAppRoot should point to: " + current_dir)
print()
print("4️⃣ CHECK APACHE ERROR LOG:")
print(" tail -50 ~/logs/error_log")
print(" (Look for Passenger errors)")
print()
print("5️⃣ VERIFY .htaccess IS BEING READ:")
print(" If AllowOverride is not set in Apache config, .htaccess is ignored")
print()
print("6️⃣ SIMPLER .htaccess (if still failing):")
print(" Try creating a minimal .htaccess with just:")
print(" PassengerEnabled on")
print()
print("=" * 70)
-8
View File
@@ -1,8 +0,0 @@
"""
WSGI entry point for production deployment
Use with Gunicorn: gunicorn wsgi:app
"""
from app import app
if __name__ == "__main__":
app.run()