Upload 10 files
Browse filesMethod 1: Upload via Web Interface
Go to your repository at https://huggingface.co/NuBest/height-conversion-tool
Click "Files and versions" tab
Click "Add file" → "Upload files" button
Drag and drop all files or click to browse and select multiple files
Add a commit message (e.g., "Add project files")
Click "Commit changes to main"
Tip: You can upload multiple files at once by selecting them all together.Method 2: Upload via Python (Recommended)This method uploads all files in one command:pythonfrom huggingface_hub import login, upload_folder
# Step 1: Login with your Hugging Face credentials
login()
# Step 2: Upload entire folder to repository
upload_folder(
folder_path=".", # Current directory with all files
repo_id="NuBest/height-conversion-tool",
repo_type="model"
)Installation:
bashpip install huggingface_hubUsage:
bashpython upload_script.py
Method 3: Upload via Git (For Developers)
This method uses Git commands for version control:
bash# Step 1: Clone your repository
git clone https://huggingface.co/NuBest/height-conversion-tool
cd height-conversion-tool
# Step 2: Copy all project files into this directory
# (Copy README.md, height_converter.py, requirements.txt, etc.)
# Step 3: Add files to Git
git add .
# Step 4: Commit with a message
git commit -m "Add complete project files and documentation"
# Step 5: Push to Hugging Face
git push
For first-time Git setup:
bash# Configure git with your Hugging Face credentials
git config user.email "your-email@example.com"
git config user.name "Your Name"
# Use your HF token as password when pushing
# Username: your-hf-username
# Password: your-hf-access-token
Method 4: Upload via CLI (huggingface-cli)
Quick command-line upload:
bash# Install CLI
pip install huggingface_hub[cli]
# Login
huggingface-cli login
# Upload a single file
huggingface-cli upload NuBest/height-conversion-tool README.md
# Upload entire directory
huggingface-cli upload NuBest/height-conversion-tool . --repo-type=model
- CONTRIBUTING.md +315 -0
- LICENSE +85 -0
- README.md +287 -7
- example_usage.py +91 -0
- gitignore +139 -0
- height_converter.py +270 -0
- requirements-dev.txt +22 -0
- requirements.txt +25 -0
- setup.py +66 -0
- test_height_converter.py +149 -0
|
@@ -0,0 +1,315 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing to Height Conversion Tool
|
| 2 |
+
|
| 3 |
+
Thank you for your interest in contributing to the Height Conversion Tool! We welcome contributions from the community.
|
| 4 |
+
|
| 5 |
+
## Table of Contents
|
| 6 |
+
|
| 7 |
+
- [Code of Conduct](#code-of-conduct)
|
| 8 |
+
- [Getting Started](#getting-started)
|
| 9 |
+
- [How to Contribute](#how-to-contribute)
|
| 10 |
+
- [Development Setup](#development-setup)
|
| 11 |
+
- [Coding Standards](#coding-standards)
|
| 12 |
+
- [Testing Guidelines](#testing-guidelines)
|
| 13 |
+
- [Submitting Changes](#submitting-changes)
|
| 14 |
+
- [Reporting Bugs](#reporting-bugs)
|
| 15 |
+
- [Suggesting Enhancements](#suggesting-enhancements)
|
| 16 |
+
|
| 17 |
+
## Code of Conduct
|
| 18 |
+
|
| 19 |
+
This project follows a simple code of conduct: be respectful, be constructive, and be collaborative. We aim to maintain a welcoming environment for all contributors.
|
| 20 |
+
|
| 21 |
+
## Getting Started
|
| 22 |
+
|
| 23 |
+
1. **Fork the repository** on Hugging Face
|
| 24 |
+
2. **Clone your fork** to your local machine:
|
| 25 |
+
```bash
|
| 26 |
+
git clone https://huggingface.co/YOUR_USERNAME/height-conversion-tool
|
| 27 |
+
cd height-conversion-tool
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
3. **Set up development environment** (see below)
|
| 31 |
+
|
| 32 |
+
## How to Contribute
|
| 33 |
+
|
| 34 |
+
There are many ways to contribute:
|
| 35 |
+
|
| 36 |
+
- 🐛 **Report bugs** - Help us identify and fix issues
|
| 37 |
+
- ✨ **Suggest features** - Share ideas for improvements
|
| 38 |
+
- 📝 **Improve documentation** - Help others understand the tool better
|
| 39 |
+
- 🔧 **Submit bug fixes** - Fix issues you've found
|
| 40 |
+
- 🚀 **Add new features** - Implement new functionality
|
| 41 |
+
- ✅ **Write tests** - Improve test coverage
|
| 42 |
+
- 🌍 **Add translations** - Help make the tool multilingual
|
| 43 |
+
|
| 44 |
+
## Development Setup
|
| 45 |
+
|
| 46 |
+
### Prerequisites
|
| 47 |
+
|
| 48 |
+
- Python 3.8 or higher
|
| 49 |
+
- pip
|
| 50 |
+
- git
|
| 51 |
+
|
| 52 |
+
### Installation Steps
|
| 53 |
+
|
| 54 |
+
1. **Create a virtual environment**:
|
| 55 |
+
```bash
|
| 56 |
+
python -m venv venv
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
2. **Activate the virtual environment**:
|
| 60 |
+
- On Linux/Mac:
|
| 61 |
+
```bash
|
| 62 |
+
source venv/bin/activate
|
| 63 |
+
```
|
| 64 |
+
- On Windows:
|
| 65 |
+
```bash
|
| 66 |
+
venv\Scripts\activate
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
3. **Install development dependencies**:
|
| 70 |
+
```bash
|
| 71 |
+
pip install -r requirements-dev.txt
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
4. **Install the package in editable mode**:
|
| 75 |
+
```bash
|
| 76 |
+
pip install -e .
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
### Verify Installation
|
| 80 |
+
|
| 81 |
+
Run the tests to make sure everything is working:
|
| 82 |
+
```bash
|
| 83 |
+
pytest tests/ -v
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## Coding Standards
|
| 87 |
+
|
| 88 |
+
### Python Style Guide
|
| 89 |
+
|
| 90 |
+
We follow [PEP 8](https://pep8.org/) with some modifications:
|
| 91 |
+
|
| 92 |
+
- **Line length**: Maximum 100 characters
|
| 93 |
+
- **Indentation**: 4 spaces (no tabs)
|
| 94 |
+
- **Quotes**: Use double quotes for strings
|
| 95 |
+
- **Imports**: Group and sort alphabetically
|
| 96 |
+
|
| 97 |
+
### Code Formatting
|
| 98 |
+
|
| 99 |
+
We use **Black** for automatic code formatting:
|
| 100 |
+
```bash
|
| 101 |
+
black height_converter.py
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
### Linting
|
| 105 |
+
|
| 106 |
+
We use **flake8** for linting:
|
| 107 |
+
```bash
|
| 108 |
+
flake8 height_converter.py
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
### Type Hints
|
| 112 |
+
|
| 113 |
+
Please include type hints for function parameters and return values:
|
| 114 |
+
```python
|
| 115 |
+
def feet_to_cm(self, feet: int, inches: float = 0) -> float:
|
| 116 |
+
"""Convert feet and inches to centimeters."""
|
| 117 |
+
pass
|
| 118 |
+
```
|
| 119 |
+
|
| 120 |
+
## Testing Guidelines
|
| 121 |
+
|
| 122 |
+
### Writing Tests
|
| 123 |
+
|
| 124 |
+
- Place tests in the `tests/` directory
|
| 125 |
+
- Name test files with `test_` prefix
|
| 126 |
+
- Name test functions with `test_` prefix
|
| 127 |
+
- Use descriptive test names
|
| 128 |
+
|
| 129 |
+
Example:
|
| 130 |
+
```python
|
| 131 |
+
def test_feet_to_cm_with_decimal_inches():
|
| 132 |
+
"""Test conversion with decimal inch values."""
|
| 133 |
+
converter = HeightConverter()
|
| 134 |
+
result = converter.feet_to_cm(5, 10.5)
|
| 135 |
+
assert result == pytest.approx(179.07, rel=0.01)
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
+
### Running Tests
|
| 139 |
+
|
| 140 |
+
Run all tests:
|
| 141 |
+
```bash
|
| 142 |
+
pytest
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
Run with coverage:
|
| 146 |
+
```bash
|
| 147 |
+
pytest --cov=height_converter --cov-report=html
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
Run specific test file:
|
| 151 |
+
```bash
|
| 152 |
+
pytest tests/test_height_converter.py -v
|
| 153 |
+
```
|
| 154 |
+
|
| 155 |
+
### Test Coverage
|
| 156 |
+
|
| 157 |
+
We aim for at least 90% test coverage. Check coverage with:
|
| 158 |
+
```bash
|
| 159 |
+
pytest --cov=height_converter --cov-report=term-missing
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
## Submitting Changes
|
| 163 |
+
|
| 164 |
+
### Branching Strategy
|
| 165 |
+
|
| 166 |
+
1. **Create a new branch** from `main`:
|
| 167 |
+
```bash
|
| 168 |
+
git checkout -b feature/your-feature-name
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
Branch naming conventions:
|
| 172 |
+
- `feature/` - New features
|
| 173 |
+
- `bugfix/` - Bug fixes
|
| 174 |
+
- `docs/` - Documentation updates
|
| 175 |
+
- `test/` - Test improvements
|
| 176 |
+
|
| 177 |
+
2. **Make your changes** following our coding standards
|
| 178 |
+
|
| 179 |
+
3. **Write or update tests** for your changes
|
| 180 |
+
|
| 181 |
+
4. **Run the test suite** to ensure everything passes:
|
| 182 |
+
```bash
|
| 183 |
+
pytest
|
| 184 |
+
black .
|
| 185 |
+
flake8
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
5. **Commit your changes** with a clear message:
|
| 189 |
+
```bash
|
| 190 |
+
git add .
|
| 191 |
+
git commit -m "Add feature: description of your changes"
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
Commit message format:
|
| 195 |
+
```
|
| 196 |
+
<type>: <short description>
|
| 197 |
+
|
| 198 |
+
<optional detailed description>
|
| 199 |
+
|
| 200 |
+
<optional footer>
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
Types: `feat`, `fix`, `docs`, `test`, `refactor`, `style`, `chore`
|
| 204 |
+
|
| 205 |
+
6. **Push to your fork**:
|
| 206 |
+
```bash
|
| 207 |
+
git push origin feature/your-feature-name
|
| 208 |
+
```
|
| 209 |
+
|
| 210 |
+
7. **Create a Pull Request** on Hugging Face
|
| 211 |
+
|
| 212 |
+
### Pull Request Guidelines
|
| 213 |
+
|
| 214 |
+
Your PR should:
|
| 215 |
+
|
| 216 |
+
- ✅ Have a clear title and description
|
| 217 |
+
- ✅ Reference any related issues
|
| 218 |
+
- ✅ Include tests for new functionality
|
| 219 |
+
- ✅ Update documentation if needed
|
| 220 |
+
- ✅ Pass all CI checks
|
| 221 |
+
- ✅ Have no merge conflicts
|
| 222 |
+
|
| 223 |
+
**PR Template:**
|
| 224 |
+
```markdown
|
| 225 |
+
## Description
|
| 226 |
+
Brief description of your changes
|
| 227 |
+
|
| 228 |
+
## Type of Change
|
| 229 |
+
- [ ] Bug fix
|
| 230 |
+
- [ ] New feature
|
| 231 |
+
- [ ] Documentation update
|
| 232 |
+
- [ ] Performance improvement
|
| 233 |
+
|
| 234 |
+
## Testing
|
| 235 |
+
Describe how you tested your changes
|
| 236 |
+
|
| 237 |
+
## Checklist
|
| 238 |
+
- [ ] Code follows style guidelines
|
| 239 |
+
- [ ] Tests added/updated
|
| 240 |
+
- [ ] Documentation updated
|
| 241 |
+
- [ ] All tests passing
|
| 242 |
+
```
|
| 243 |
+
|
| 244 |
+
## Reporting Bugs
|
| 245 |
+
|
| 246 |
+
### Before Submitting a Bug Report
|
| 247 |
+
|
| 248 |
+
- Check the documentation
|
| 249 |
+
- Search existing issues
|
| 250 |
+
- Try the latest version
|
| 251 |
+
|
| 252 |
+
### How to Submit a Good Bug Report
|
| 253 |
+
|
| 254 |
+
Include:
|
| 255 |
+
|
| 256 |
+
1. **Clear title** - Concise summary of the issue
|
| 257 |
+
2. **Description** - Detailed explanation
|
| 258 |
+
3. **Steps to reproduce** - Exact steps to trigger the bug
|
| 259 |
+
4. **Expected behavior** - What should happen
|
| 260 |
+
5. **Actual behavior** - What actually happens
|
| 261 |
+
6. **Environment** - OS, Python version, package version
|
| 262 |
+
7. **Code sample** - Minimal reproducible example
|
| 263 |
+
|
| 264 |
+
**Template:**
|
| 265 |
+
```markdown
|
| 266 |
+
**Environment:**
|
| 267 |
+
- OS: [e.g., Ubuntu 22.04]
|
| 268 |
+
- Python version: [e.g., 3.10.5]
|
| 269 |
+
- Package version: [e.g., 1.0.0]
|
| 270 |
+
|
| 271 |
+
**Description:**
|
| 272 |
+
[Clear description of the bug]
|
| 273 |
+
|
| 274 |
+
**Steps to Reproduce:**
|
| 275 |
+
1. Step 1
|
| 276 |
+
2. Step 2
|
| 277 |
+
3. Step 3
|
| 278 |
+
|
| 279 |
+
**Expected Behavior:**
|
| 280 |
+
[What should happen]
|
| 281 |
+
|
| 282 |
+
**Actual Behavior:**
|
| 283 |
+
[What actually happens]
|
| 284 |
+
|
| 285 |
+
**Code Sample:**
|
| 286 |
+
```python
|
| 287 |
+
# Minimal code to reproduce the issue
|
| 288 |
+
```
|
| 289 |
+
```
|
| 290 |
+
|
| 291 |
+
## Suggesting Enhancements
|
| 292 |
+
|
| 293 |
+
We welcome enhancement suggestions! Please include:
|
| 294 |
+
|
| 295 |
+
1. **Use case** - Why is this enhancement needed?
|
| 296 |
+
2. **Proposed solution** - How should it work?
|
| 297 |
+
3. **Alternatives** - Other approaches considered
|
| 298 |
+
4. **Additional context** - Screenshots, examples, etc.
|
| 299 |
+
|
| 300 |
+
## Questions?
|
| 301 |
+
|
| 302 |
+
If you have questions about contributing, feel free to:
|
| 303 |
+
|
| 304 |
+
- Open a discussion on Hugging Face
|
| 305 |
+
- Ask in the community forum
|
| 306 |
+
- Contact the maintainers
|
| 307 |
+
|
| 308 |
+
## Recognition
|
| 309 |
+
|
| 310 |
+
Contributors will be recognized in:
|
| 311 |
+
- The project README
|
| 312 |
+
- Release notes
|
| 313 |
+
- Our hall of fame (coming soon!)
|
| 314 |
+
|
| 315 |
+
Thank you for contributing to Height Conversion Tool! 🎉
|
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Apache License
|
| 2 |
+
Version 2.0, January 2004
|
| 3 |
+
http://www.apache.org/licenses/
|
| 4 |
+
|
| 5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 6 |
+
|
| 7 |
+
1. Definitions.
|
| 8 |
+
|
| 9 |
+
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
| 10 |
+
|
| 11 |
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
| 12 |
+
|
| 13 |
+
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
| 14 |
+
|
| 15 |
+
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
| 16 |
+
|
| 17 |
+
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
| 18 |
+
|
| 19 |
+
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
| 20 |
+
|
| 21 |
+
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work.
|
| 22 |
+
|
| 23 |
+
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
| 24 |
+
|
| 25 |
+
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
| 26 |
+
|
| 27 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
| 28 |
+
|
| 29 |
+
2. Grant of Copyright License.
|
| 30 |
+
|
| 31 |
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
| 32 |
+
|
| 33 |
+
3. Grant of Patent License.
|
| 34 |
+
|
| 35 |
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
| 36 |
+
|
| 37 |
+
4. Redistribution.
|
| 38 |
+
|
| 39 |
+
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
| 40 |
+
|
| 41 |
+
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
| 42 |
+
|
| 43 |
+
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
| 44 |
+
|
| 45 |
+
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
| 46 |
+
|
| 47 |
+
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
| 48 |
+
|
| 49 |
+
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
| 50 |
+
|
| 51 |
+
5. Submission of Contributions.
|
| 52 |
+
|
| 53 |
+
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
| 54 |
+
|
| 55 |
+
6. Trademarks.
|
| 56 |
+
|
| 57 |
+
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
| 58 |
+
|
| 59 |
+
7. Disclaimer of Warranty.
|
| 60 |
+
|
| 61 |
+
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
| 62 |
+
|
| 63 |
+
8. Limitation of Liability.
|
| 64 |
+
|
| 65 |
+
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
| 66 |
+
|
| 67 |
+
9. Accepting Warranty or Additional Liability.
|
| 68 |
+
|
| 69 |
+
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
| 70 |
+
|
| 71 |
+
END OF TERMS AND CONDITIONS
|
| 72 |
+
|
| 73 |
+
Copyright 2025 NuBest Team
|
| 74 |
+
|
| 75 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 76 |
+
you may not use this file except in compliance with the License.
|
| 77 |
+
You may obtain a copy of the License at
|
| 78 |
+
|
| 79 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 80 |
+
|
| 81 |
+
Unless required by applicable law or agreed to in writing, software
|
| 82 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 83 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 84 |
+
See the License for the specific language governing permissions and
|
| 85 |
+
limitations under the License.
|
|
@@ -1,12 +1,292 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
-
language:
|
| 4 |
-
- en
|
| 5 |
-
pipeline_tag: unconditional-image-generation
|
| 6 |
tags:
|
| 7 |
-
- unit-converter
|
| 8 |
- height-conversion
|
|
|
|
| 9 |
- measurement
|
| 10 |
-
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
|
|
|
|
|
|
|
|
|
| 3 |
tags:
|
|
|
|
| 4 |
- height-conversion
|
| 5 |
+
- utility
|
| 6 |
- measurement
|
| 7 |
+
- unit-conversion
|
| 8 |
+
language:
|
| 9 |
+
- en
|
| 10 |
+
- vi
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# Height Conversion Tool
|
| 14 |
+
|
| 15 |
+
A simple and efficient tool for converting height measurements between different units (feet/inches, centimeters, meters).
|
| 16 |
+
|
| 17 |
+
## Model Overview
|
| 18 |
+
|
| 19 |
+
This tool provides accurate height conversions between various measurement systems commonly used around the world. It supports bidirectional conversions and handles multiple input formats.
|
| 20 |
+
|
| 21 |
+
## Features
|
| 22 |
+
|
| 23 |
+
- **Multiple Unit Support**: Convert between feet/inches, centimeters, and meters
|
| 24 |
+
- **Flexible Input**: Accepts various input formats (e.g., "5'10\"", "178 cm", "1.78 m")
|
| 25 |
+
- **High Accuracy**: Maintains precision across conversions
|
| 26 |
+
- **Easy to Use**: Simple API with clear documentation
|
| 27 |
+
- **Bilingual**: Supports English and Vietnamese
|
| 28 |
+
|
| 29 |
+
## Supported Conversions
|
| 30 |
+
|
| 31 |
+
| From | To | Example |
|
| 32 |
+
|------|-----|---------|
|
| 33 |
+
| Feet & Inches | Centimeters | 5'10" → 177.8 cm |
|
| 34 |
+
| Centimeters | Feet & Inches | 180 cm → 5'11" |
|
| 35 |
+
| Meters | Feet & Inches | 1.75 m → 5'9" |
|
| 36 |
+
| Feet & Inches | Meters | 6'0" → 1.83 m |
|
| 37 |
+
| Centimeters | Meters | 170 cm → 1.7 m |
|
| 38 |
+
|
| 39 |
+
## Installation
|
| 40 |
+
|
| 41 |
+
```bash
|
| 42 |
+
pip install height-conversion-tool
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
Or clone this repository:
|
| 46 |
+
|
| 47 |
+
```bash
|
| 48 |
+
git clone https://huggingface.co/NuBest/height-conversion-tool
|
| 49 |
+
cd height-conversion-tool
|
| 50 |
+
pip install -r requirements.txt
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
## Quick Start
|
| 54 |
+
|
| 55 |
+
### Python Usage
|
| 56 |
+
|
| 57 |
+
```python
|
| 58 |
+
from height_converter import HeightConverter
|
| 59 |
+
|
| 60 |
+
# Initialize converter
|
| 61 |
+
converter = HeightConverter()
|
| 62 |
+
|
| 63 |
+
# Convert from feet/inches to centimeters
|
| 64 |
+
height_cm = converter.feet_to_cm(5, 10) # 5 feet 10 inches
|
| 65 |
+
print(f"Height: {height_cm} cm") # Output: Height: 177.8 cm
|
| 66 |
+
|
| 67 |
+
# Convert from centimeters to feet/inches
|
| 68 |
+
feet, inches = converter.cm_to_feet(180)
|
| 69 |
+
print(f"Height: {feet}'{inches}\"") # Output: Height: 5'11"
|
| 70 |
+
|
| 71 |
+
# String input format
|
| 72 |
+
result = converter.convert("5'10\"", to_unit="cm")
|
| 73 |
+
print(result) # Output: 177.8 cm
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
### Command Line Usage
|
| 77 |
+
|
| 78 |
+
```bash
|
| 79 |
+
# Convert height
|
| 80 |
+
python height_converter.py --input "5'10\"" --output cm
|
| 81 |
+
|
| 82 |
+
# Multiple conversions
|
| 83 |
+
python height_converter.py --input 180 --from cm --to feet
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## API Reference
|
| 87 |
+
|
| 88 |
+
### HeightConverter Class
|
| 89 |
+
|
| 90 |
+
#### Methods
|
| 91 |
+
|
| 92 |
+
**`feet_to_cm(feet: int, inches: float = 0) -> float`**
|
| 93 |
+
- Converts feet and inches to centimeters
|
| 94 |
+
- Parameters:
|
| 95 |
+
- `feet`: Number of feet
|
| 96 |
+
- `inches`: Number of inches (optional, default: 0)
|
| 97 |
+
- Returns: Height in centimeters
|
| 98 |
+
|
| 99 |
+
**`cm_to_feet(cm: float) -> tuple[int, float]`**
|
| 100 |
+
- Converts centimeters to feet and inches
|
| 101 |
+
- Parameters:
|
| 102 |
+
- `cm`: Height in centimeters
|
| 103 |
+
- Returns: Tuple of (feet, inches)
|
| 104 |
+
|
| 105 |
+
**`meters_to_feet(meters: float) -> tuple[int, float]`**
|
| 106 |
+
- Converts meters to feet and inches
|
| 107 |
+
- Parameters:
|
| 108 |
+
- `meters`: Height in meters
|
| 109 |
+
- Returns: Tuple of (feet, inches)
|
| 110 |
+
|
| 111 |
+
**`convert(input_str: str, to_unit: str = "cm") -> str`**
|
| 112 |
+
- Flexible conversion from string input
|
| 113 |
+
- Parameters:
|
| 114 |
+
- `input_str`: Height string (e.g., "5'10\"", "180cm", "1.8m")
|
| 115 |
+
- `to_unit`: Target unit ("cm", "feet", "meters")
|
| 116 |
+
- Returns: Converted height as string
|
| 117 |
+
|
| 118 |
+
## Use Cases
|
| 119 |
+
|
| 120 |
+
- **Healthcare**: Converting patient height measurements between metric and imperial systems
|
| 121 |
+
- **Fitness Apps**: Standardizing height inputs across different regions
|
| 122 |
+
- **E-commerce**: Converting size charts for international customers
|
| 123 |
+
- **Travel Apps**: Helping users understand height requirements in different countries
|
| 124 |
+
- **Education**: Teaching measurement conversions
|
| 125 |
+
|
| 126 |
+
## Technical Details
|
| 127 |
+
|
| 128 |
+
### Conversion Formulas
|
| 129 |
+
|
| 130 |
+
- 1 inch = 2.54 cm
|
| 131 |
+
- 1 foot = 12 inches = 30.48 cm
|
| 132 |
+
- 1 meter = 100 cm = 3.28084 feet
|
| 133 |
+
|
| 134 |
+
### Accuracy
|
| 135 |
+
|
| 136 |
+
The tool maintains precision up to 2 decimal places for centimeters and meters, and up to 1 decimal place for inches.
|
| 137 |
+
|
| 138 |
+
## Examples
|
| 139 |
+
|
| 140 |
+
### Example 1: Basic Conversion
|
| 141 |
+
|
| 142 |
+
```python
|
| 143 |
+
from height_converter import HeightConverter
|
| 144 |
+
|
| 145 |
+
converter = HeightConverter()
|
| 146 |
+
|
| 147 |
+
# Convert 6 feet to centimeters
|
| 148 |
+
result = converter.feet_to_cm(6, 0)
|
| 149 |
+
print(f"6 feet = {result} cm") # Output: 6 feet = 182.88 cm
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
### Example 2: Batch Conversion
|
| 153 |
+
|
| 154 |
+
```python
|
| 155 |
+
heights_cm = [150, 160, 170, 180, 190]
|
| 156 |
+
|
| 157 |
+
for height in heights_cm:
|
| 158 |
+
feet, inches = converter.cm_to_feet(height)
|
| 159 |
+
print(f"{height} cm = {feet}'{inches:.1f}\"")
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
Output:
|
| 163 |
+
```
|
| 164 |
+
150 cm = 4'11.1"
|
| 165 |
+
160 cm = 5'3.0"
|
| 166 |
+
170 cm = 5'7.0"
|
| 167 |
+
180 cm = 5'10.9"
|
| 168 |
+
190 cm = 6'2.8"
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
### Example 3: Web Integration
|
| 172 |
+
|
| 173 |
+
```python
|
| 174 |
+
from flask import Flask, request, jsonify
|
| 175 |
+
from height_converter import HeightConverter
|
| 176 |
+
|
| 177 |
+
app = Flask(__name__)
|
| 178 |
+
converter = HeightConverter()
|
| 179 |
+
|
| 180 |
+
@app.route('/convert', methods=['POST'])
|
| 181 |
+
def convert_height():
|
| 182 |
+
data = request.json
|
| 183 |
+
input_height = data.get('height')
|
| 184 |
+
to_unit = data.get('to_unit', 'cm')
|
| 185 |
+
|
| 186 |
+
result = converter.convert(input_height, to_unit)
|
| 187 |
+
return jsonify({'result': result})
|
| 188 |
+
|
| 189 |
+
if __name__ == '__main__':
|
| 190 |
+
app.run(debug=True)
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
## Testing
|
| 194 |
+
|
| 195 |
+
Run the test suite:
|
| 196 |
+
|
| 197 |
+
```bash
|
| 198 |
+
python -m pytest tests/
|
| 199 |
+
```
|
| 200 |
+
|
| 201 |
+
Run specific tests:
|
| 202 |
+
|
| 203 |
+
```bash
|
| 204 |
+
python -m pytest tests/test_converter.py -v
|
| 205 |
+
```
|
| 206 |
+
|
| 207 |
+
## Contributing
|
| 208 |
+
|
| 209 |
+
We welcome contributions! Please follow these steps:
|
| 210 |
+
|
| 211 |
+
1. Fork the repository
|
| 212 |
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
| 213 |
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
| 214 |
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
| 215 |
+
5. Open a Pull Request
|
| 216 |
+
|
| 217 |
+
### Development Setup
|
| 218 |
+
|
| 219 |
+
```bash
|
| 220 |
+
# Clone repository
|
| 221 |
+
git clone https://huggingface.co/NuBest/height-conversion-tool
|
| 222 |
+
cd height-conversion-tool
|
| 223 |
+
|
| 224 |
+
# Create virtual environment
|
| 225 |
+
python -m venv venv
|
| 226 |
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
| 227 |
+
|
| 228 |
+
# Install development dependencies
|
| 229 |
+
pip install -r requirements-dev.txt
|
| 230 |
+
|
| 231 |
+
# Run tests
|
| 232 |
+
pytest
|
| 233 |
+
```
|
| 234 |
+
|
| 235 |
+
## License
|
| 236 |
+
|
| 237 |
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
| 238 |
+
|
| 239 |
+
## Citation
|
| 240 |
+
|
| 241 |
+
If you use this tool in your research or project, please cite:
|
| 242 |
+
|
| 243 |
+
```bibtex
|
| 244 |
+
@software{height_conversion_tool,
|
| 245 |
+
author = {NuBest},
|
| 246 |
+
title = {Height Conversion Tool},
|
| 247 |
+
year = {2025},
|
| 248 |
+
url = {https://huggingface.co/NuBest/height-conversion-tool}
|
| 249 |
+
}
|
| 250 |
+
```
|
| 251 |
+
|
| 252 |
+
## Support
|
| 253 |
+
|
| 254 |
+
- **Issues**: [GitHub Issues](https://huggingface.co/NuBest/height-conversion-tool/discussions)
|
| 255 |
+
- **Discussions**: [Community Forum](https://huggingface.co/NuBest/height-conversion-tool/discussions)
|
| 256 |
+
- **Email**: support@nubest.com
|
| 257 |
+
|
| 258 |
+
## Changelog
|
| 259 |
+
|
| 260 |
+
### Version 1.0.0 (2025-01-29)
|
| 261 |
+
- Initial release
|
| 262 |
+
- Support for feet/inches, centimeters, and meters
|
| 263 |
+
- Command line interface
|
| 264 |
+
- Python API
|
| 265 |
+
- Comprehensive test suite
|
| 266 |
+
|
| 267 |
+
## Acknowledgments
|
| 268 |
+
|
| 269 |
+
- Built with Python 3.8+
|
| 270 |
+
- Inspired by the need for accurate height conversions in international applications
|
| 271 |
+
- Special thanks to the Hugging Face community
|
| 272 |
+
|
| 273 |
+
## FAQ
|
| 274 |
+
|
| 275 |
+
**Q: What's the maximum height that can be converted?**
|
| 276 |
+
A: The tool supports heights up to 999 cm (32'9") to cover all practical use cases.
|
| 277 |
+
|
| 278 |
+
**Q: How accurate are the conversions?**
|
| 279 |
+
A: Conversions maintain precision up to 2 decimal places, which is sufficient for all practical purposes.
|
| 280 |
+
|
| 281 |
+
**Q: Can I use this in a commercial application?**
|
| 282 |
+
A: Yes, the Apache 2.0 license allows commercial use with proper attribution.
|
| 283 |
+
|
| 284 |
+
**Q: Does it support other units like yards or kilometers?**
|
| 285 |
+
A: Currently, the tool focuses on the most commonly used units (feet/inches, cm, meters). Additional units may be added in future versions.
|
| 286 |
+
|
| 287 |
+
**Q: How do I handle invalid input?**
|
| 288 |
+
A: The tool includes input validation and raises clear error messages for invalid inputs.
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
Made with ❤️ by NuBest Team
|
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Example usage of Height Conversion Tool
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from height_converter import HeightConverter
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def main():
|
| 9 |
+
"""Demonstrate various uses of the HeightConverter."""
|
| 10 |
+
|
| 11 |
+
# Initialize converter
|
| 12 |
+
converter = HeightConverter()
|
| 13 |
+
|
| 14 |
+
print("=" * 60)
|
| 15 |
+
print("Height Conversion Tool - Examples")
|
| 16 |
+
print("=" * 60)
|
| 17 |
+
|
| 18 |
+
# Example 1: Convert feet/inches to cm
|
| 19 |
+
print("\n1. Convert 5'10\" to centimeters:")
|
| 20 |
+
height_cm = converter.feet_to_cm(5, 10)
|
| 21 |
+
print(f" Result: {height_cm} cm")
|
| 22 |
+
|
| 23 |
+
# Example 2: Convert cm to feet/inches
|
| 24 |
+
print("\n2. Convert 180 cm to feet/inches:")
|
| 25 |
+
feet, inches = converter.cm_to_feet(180)
|
| 26 |
+
print(f" Result: {feet}'{inches}\"")
|
| 27 |
+
|
| 28 |
+
# Example 3: Convert meters to feet/inches
|
| 29 |
+
print("\n3. Convert 1.75 meters to feet/inches:")
|
| 30 |
+
feet, inches = converter.meters_to_feet(1.75)
|
| 31 |
+
print(f" Result: {feet}'{inches}\"")
|
| 32 |
+
|
| 33 |
+
# Example 4: Convert feet to meters
|
| 34 |
+
print("\n4. Convert 6 feet to meters:")
|
| 35 |
+
meters = converter.feet_to_meters(6, 0)
|
| 36 |
+
print(f" Result: {meters} m")
|
| 37 |
+
|
| 38 |
+
# Example 5: Using string input
|
| 39 |
+
print("\n5. Convert using string input:")
|
| 40 |
+
heights = ["5'10\"", "180cm", "1.75m"]
|
| 41 |
+
for height in heights:
|
| 42 |
+
result_cm = converter.convert(height, "cm")
|
| 43 |
+
result_feet = converter.convert(height, "feet")
|
| 44 |
+
print(f" {height:10} = {result_cm:12} = {result_feet}")
|
| 45 |
+
|
| 46 |
+
# Example 6: Batch conversion
|
| 47 |
+
print("\n6. Batch conversion (cm to feet/inches):")
|
| 48 |
+
heights_cm = [150, 160, 170, 180, 190]
|
| 49 |
+
print(f" {'CM':<6} {'Feet/Inches':<12}")
|
| 50 |
+
print(f" {'-'*6} {'-'*12}")
|
| 51 |
+
for height in heights_cm:
|
| 52 |
+
feet, inches = converter.cm_to_feet(height)
|
| 53 |
+
print(f" {height:<6} {feet}'{inches:.1f}\"")
|
| 54 |
+
|
| 55 |
+
# Example 7: Height comparison
|
| 56 |
+
print("\n7. Height comparison:")
|
| 57 |
+
person1 = {"name": "Alice", "height": "5'6\""}
|
| 58 |
+
person2 = {"name": "Bob", "height": "175cm"}
|
| 59 |
+
|
| 60 |
+
alice_cm = converter.feet_to_cm(5, 6)
|
| 61 |
+
bob_cm = 175
|
| 62 |
+
|
| 63 |
+
print(f" {person1['name']}: {person1['height']} = {alice_cm} cm")
|
| 64 |
+
print(f" {person2['name']}: {person2['height']} = {bob_cm} cm")
|
| 65 |
+
|
| 66 |
+
if alice_cm > bob_cm:
|
| 67 |
+
print(f" {person1['name']} is taller by {alice_cm - bob_cm:.1f} cm")
|
| 68 |
+
elif bob_cm > alice_cm:
|
| 69 |
+
print(f" {person2['name']} is taller by {bob_cm - alice_cm:.1f} cm")
|
| 70 |
+
else:
|
| 71 |
+
print(f" They are the same height!")
|
| 72 |
+
|
| 73 |
+
# Example 8: Error handling
|
| 74 |
+
print("\n8. Error handling:")
|
| 75 |
+
try:
|
| 76 |
+
converter.feet_to_cm(-5, 10)
|
| 77 |
+
except ValueError as e:
|
| 78 |
+
print(f" Caught error: {e}")
|
| 79 |
+
|
| 80 |
+
try:
|
| 81 |
+
converter.parse_height_string("invalid input")
|
| 82 |
+
except ValueError as e:
|
| 83 |
+
print(f" Caught error: {e}")
|
| 84 |
+
|
| 85 |
+
print("\n" + "=" * 60)
|
| 86 |
+
print("Examples completed!")
|
| 87 |
+
print("=" * 60)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
if __name__ == "__main__":
|
| 91 |
+
main()
|
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
*.so
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
lib/
|
| 18 |
+
lib64/
|
| 19 |
+
parts/
|
| 20 |
+
sdist/
|
| 21 |
+
var/
|
| 22 |
+
wheels/
|
| 23 |
+
pip-wheel-metadata/
|
| 24 |
+
share/python-wheels/
|
| 25 |
+
*.egg-info/
|
| 26 |
+
.installed.cfg
|
| 27 |
+
*.egg
|
| 28 |
+
MANIFEST
|
| 29 |
+
|
| 30 |
+
# PyInstaller
|
| 31 |
+
*.manifest
|
| 32 |
+
*.spec
|
| 33 |
+
|
| 34 |
+
# Installer logs
|
| 35 |
+
pip-log.txt
|
| 36 |
+
pip-delete-this-directory.txt
|
| 37 |
+
|
| 38 |
+
# Unit test / coverage reports
|
| 39 |
+
htmlcov/
|
| 40 |
+
.tox/
|
| 41 |
+
.nox/
|
| 42 |
+
.coverage
|
| 43 |
+
.coverage.*
|
| 44 |
+
.cache
|
| 45 |
+
nosetests.xml
|
| 46 |
+
coverage.xml
|
| 47 |
+
*.cover
|
| 48 |
+
*.py,cover
|
| 49 |
+
.hypothesis/
|
| 50 |
+
.pytest_cache/
|
| 51 |
+
|
| 52 |
+
# Translations
|
| 53 |
+
*.mo
|
| 54 |
+
*.pot
|
| 55 |
+
|
| 56 |
+
# Django stuff:
|
| 57 |
+
*.log
|
| 58 |
+
local_settings.py
|
| 59 |
+
db.sqlite3
|
| 60 |
+
db.sqlite3-journal
|
| 61 |
+
|
| 62 |
+
# Flask stuff:
|
| 63 |
+
instance/
|
| 64 |
+
.webassets-cache
|
| 65 |
+
|
| 66 |
+
# Scrapy stuff:
|
| 67 |
+
.scrapy
|
| 68 |
+
|
| 69 |
+
# Sphinx documentation
|
| 70 |
+
docs/_build/
|
| 71 |
+
|
| 72 |
+
# PyBuilder
|
| 73 |
+
target/
|
| 74 |
+
|
| 75 |
+
# Jupyter Notebook
|
| 76 |
+
.ipynb_checkpoints
|
| 77 |
+
|
| 78 |
+
# IPython
|
| 79 |
+
profile_default/
|
| 80 |
+
ipython_config.py
|
| 81 |
+
|
| 82 |
+
# pyenv
|
| 83 |
+
.python-version
|
| 84 |
+
|
| 85 |
+
# pipenv
|
| 86 |
+
Pipfile.lock
|
| 87 |
+
|
| 88 |
+
# PEP 582
|
| 89 |
+
__pypackages__/
|
| 90 |
+
|
| 91 |
+
# Celery stuff
|
| 92 |
+
celerybeat-schedule
|
| 93 |
+
celerybeat.pid
|
| 94 |
+
|
| 95 |
+
# SageMath parsed files
|
| 96 |
+
*.sage.py
|
| 97 |
+
|
| 98 |
+
# Environments
|
| 99 |
+
.env
|
| 100 |
+
.venv
|
| 101 |
+
env/
|
| 102 |
+
venv/
|
| 103 |
+
ENV/
|
| 104 |
+
env.bak/
|
| 105 |
+
venv.bak/
|
| 106 |
+
|
| 107 |
+
# Spyder project settings
|
| 108 |
+
.spyderproject
|
| 109 |
+
.spyproject
|
| 110 |
+
|
| 111 |
+
# Rope project settings
|
| 112 |
+
.ropeproject
|
| 113 |
+
|
| 114 |
+
# mkdocs documentation
|
| 115 |
+
/site
|
| 116 |
+
|
| 117 |
+
# mypy
|
| 118 |
+
.mypy_cache/
|
| 119 |
+
.dmypy.json
|
| 120 |
+
dmypy.json
|
| 121 |
+
|
| 122 |
+
# Pyre type checker
|
| 123 |
+
.pyre/
|
| 124 |
+
|
| 125 |
+
# IDE
|
| 126 |
+
.vscode/
|
| 127 |
+
.idea/
|
| 128 |
+
*.swp
|
| 129 |
+
*.swo
|
| 130 |
+
*~
|
| 131 |
+
|
| 132 |
+
# OS
|
| 133 |
+
.DS_Store
|
| 134 |
+
Thumbs.db
|
| 135 |
+
|
| 136 |
+
# Project specific
|
| 137 |
+
*.log
|
| 138 |
+
temp/
|
| 139 |
+
tmp/
|
|
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Height Conversion Tool
|
| 3 |
+
A simple and efficient tool for converting height measurements between different units.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from typing import Tuple, Union
|
| 7 |
+
import re
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class HeightConverter:
|
| 11 |
+
"""Main class for height conversions."""
|
| 12 |
+
|
| 13 |
+
# Conversion constants
|
| 14 |
+
INCH_TO_CM = 2.54
|
| 15 |
+
FEET_TO_CM = 30.48
|
| 16 |
+
FEET_TO_INCH = 12
|
| 17 |
+
CM_TO_INCH = 1 / INCH_TO_CM
|
| 18 |
+
METER_TO_CM = 100
|
| 19 |
+
|
| 20 |
+
def __init__(self):
|
| 21 |
+
"""Initialize the HeightConverter."""
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
def feet_to_cm(self, feet: Union[int, float], inches: float = 0) -> float:
|
| 25 |
+
"""
|
| 26 |
+
Convert feet and inches to centimeters.
|
| 27 |
+
|
| 28 |
+
Args:
|
| 29 |
+
feet: Number of feet
|
| 30 |
+
inches: Number of inches (default: 0)
|
| 31 |
+
|
| 32 |
+
Returns:
|
| 33 |
+
Height in centimeters
|
| 34 |
+
|
| 35 |
+
Examples:
|
| 36 |
+
>>> converter = HeightConverter()
|
| 37 |
+
>>> converter.feet_to_cm(5, 10)
|
| 38 |
+
177.8
|
| 39 |
+
"""
|
| 40 |
+
if feet < 0 or inches < 0:
|
| 41 |
+
raise ValueError("Height values cannot be negative")
|
| 42 |
+
|
| 43 |
+
total_inches = (feet * self.FEET_TO_INCH) + inches
|
| 44 |
+
cm = total_inches * self.INCH_TO_CM
|
| 45 |
+
return round(cm, 2)
|
| 46 |
+
|
| 47 |
+
def cm_to_feet(self, cm: float) -> Tuple[int, float]:
|
| 48 |
+
"""
|
| 49 |
+
Convert centimeters to feet and inches.
|
| 50 |
+
|
| 51 |
+
Args:
|
| 52 |
+
cm: Height in centimeters
|
| 53 |
+
|
| 54 |
+
Returns:
|
| 55 |
+
Tuple of (feet, inches)
|
| 56 |
+
|
| 57 |
+
Examples:
|
| 58 |
+
>>> converter = HeightConverter()
|
| 59 |
+
>>> converter.cm_to_feet(180)
|
| 60 |
+
(5, 10.9)
|
| 61 |
+
"""
|
| 62 |
+
if cm < 0:
|
| 63 |
+
raise ValueError("Height cannot be negative")
|
| 64 |
+
|
| 65 |
+
total_inches = cm * self.CM_TO_INCH
|
| 66 |
+
feet = int(total_inches // self.FEET_TO_INCH)
|
| 67 |
+
inches = total_inches % self.FEET_TO_INCH
|
| 68 |
+
return feet, round(inches, 1)
|
| 69 |
+
|
| 70 |
+
def meters_to_feet(self, meters: float) -> Tuple[int, float]:
|
| 71 |
+
"""
|
| 72 |
+
Convert meters to feet and inches.
|
| 73 |
+
|
| 74 |
+
Args:
|
| 75 |
+
meters: Height in meters
|
| 76 |
+
|
| 77 |
+
Returns:
|
| 78 |
+
Tuple of (feet, inches)
|
| 79 |
+
|
| 80 |
+
Examples:
|
| 81 |
+
>>> converter = HeightConverter()
|
| 82 |
+
>>> converter.meters_to_feet(1.75)
|
| 83 |
+
(5, 8.9)
|
| 84 |
+
"""
|
| 85 |
+
if meters < 0:
|
| 86 |
+
raise ValueError("Height cannot be negative")
|
| 87 |
+
|
| 88 |
+
cm = meters * self.METER_TO_CM
|
| 89 |
+
return self.cm_to_feet(cm)
|
| 90 |
+
|
| 91 |
+
def feet_to_meters(self, feet: Union[int, float], inches: float = 0) -> float:
|
| 92 |
+
"""
|
| 93 |
+
Convert feet and inches to meters.
|
| 94 |
+
|
| 95 |
+
Args:
|
| 96 |
+
feet: Number of feet
|
| 97 |
+
inches: Number of inches (default: 0)
|
| 98 |
+
|
| 99 |
+
Returns:
|
| 100 |
+
Height in meters
|
| 101 |
+
|
| 102 |
+
Examples:
|
| 103 |
+
>>> converter = HeightConverter()
|
| 104 |
+
>>> converter.feet_to_meters(6, 0)
|
| 105 |
+
1.83
|
| 106 |
+
"""
|
| 107 |
+
cm = self.feet_to_cm(feet, inches)
|
| 108 |
+
meters = cm / self.METER_TO_CM
|
| 109 |
+
return round(meters, 2)
|
| 110 |
+
|
| 111 |
+
def cm_to_meters(self, cm: float) -> float:
|
| 112 |
+
"""
|
| 113 |
+
Convert centimeters to meters.
|
| 114 |
+
|
| 115 |
+
Args:
|
| 116 |
+
cm: Height in centimeters
|
| 117 |
+
|
| 118 |
+
Returns:
|
| 119 |
+
Height in meters
|
| 120 |
+
"""
|
| 121 |
+
if cm < 0:
|
| 122 |
+
raise ValueError("Height cannot be negative")
|
| 123 |
+
|
| 124 |
+
return round(cm / self.METER_TO_CM, 2)
|
| 125 |
+
|
| 126 |
+
def meters_to_cm(self, meters: float) -> float:
|
| 127 |
+
"""
|
| 128 |
+
Convert meters to centimeters.
|
| 129 |
+
|
| 130 |
+
Args:
|
| 131 |
+
meters: Height in meters
|
| 132 |
+
|
| 133 |
+
Returns:
|
| 134 |
+
Height in centimeters
|
| 135 |
+
"""
|
| 136 |
+
if meters < 0:
|
| 137 |
+
raise ValueError("Height cannot be negative")
|
| 138 |
+
|
| 139 |
+
return round(meters * self.METER_TO_CM, 2)
|
| 140 |
+
|
| 141 |
+
def parse_height_string(self, height_str: str) -> dict:
|
| 142 |
+
"""
|
| 143 |
+
Parse a height string into its components.
|
| 144 |
+
|
| 145 |
+
Args:
|
| 146 |
+
height_str: Height string (e.g., "5'10\"", "180cm", "1.8m")
|
| 147 |
+
|
| 148 |
+
Returns:
|
| 149 |
+
Dictionary with parsed values and unit
|
| 150 |
+
|
| 151 |
+
Examples:
|
| 152 |
+
>>> converter = HeightConverter()
|
| 153 |
+
>>> converter.parse_height_string("5'10\"")
|
| 154 |
+
{'feet': 5, 'inches': 10, 'unit': 'feet'}
|
| 155 |
+
"""
|
| 156 |
+
height_str = height_str.strip().lower()
|
| 157 |
+
|
| 158 |
+
# Pattern for feet and inches (5'10", 5'10, 5ft10in, etc.)
|
| 159 |
+
feet_pattern = r"(\d+)(?:'|ft|feet)\s*(\d+(?:\.\d+)?)?(?:\"|in|inches)?"
|
| 160 |
+
match = re.match(feet_pattern, height_str)
|
| 161 |
+
if match:
|
| 162 |
+
feet = int(match.group(1))
|
| 163 |
+
inches = float(match.group(2)) if match.group(2) else 0
|
| 164 |
+
return {'feet': feet, 'inches': inches, 'unit': 'feet'}
|
| 165 |
+
|
| 166 |
+
# Pattern for centimeters (180cm, 180 cm)
|
| 167 |
+
cm_pattern = r"(\d+(?:\.\d+)?)\s*cm"
|
| 168 |
+
match = re.match(cm_pattern, height_str)
|
| 169 |
+
if match:
|
| 170 |
+
cm = float(match.group(1))
|
| 171 |
+
return {'cm': cm, 'unit': 'cm'}
|
| 172 |
+
|
| 173 |
+
# Pattern for meters (1.8m, 1.8 m)
|
| 174 |
+
m_pattern = r"(\d+(?:\.\d+)?)\s*m(?:eters?)?"
|
| 175 |
+
match = re.match(m_pattern, height_str)
|
| 176 |
+
if match:
|
| 177 |
+
meters = float(match.group(1))
|
| 178 |
+
return {'meters': meters, 'unit': 'meters'}
|
| 179 |
+
|
| 180 |
+
raise ValueError(f"Unable to parse height string: {height_str}")
|
| 181 |
+
|
| 182 |
+
def convert(self, input_str: str, to_unit: str = "cm") -> str:
|
| 183 |
+
"""
|
| 184 |
+
Flexible conversion from string input.
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
input_str: Height string (e.g., "5'10\"", "180cm", "1.8m")
|
| 188 |
+
to_unit: Target unit ("cm", "feet", "meters")
|
| 189 |
+
|
| 190 |
+
Returns:
|
| 191 |
+
Converted height as formatted string
|
| 192 |
+
|
| 193 |
+
Examples:
|
| 194 |
+
>>> converter = HeightConverter()
|
| 195 |
+
>>> converter.convert("5'10\"", "cm")
|
| 196 |
+
'177.8 cm'
|
| 197 |
+
"""
|
| 198 |
+
parsed = self.parse_height_string(input_str)
|
| 199 |
+
to_unit = to_unit.lower()
|
| 200 |
+
|
| 201 |
+
# Convert to target unit
|
| 202 |
+
if to_unit == "cm":
|
| 203 |
+
if parsed['unit'] == 'feet':
|
| 204 |
+
result = self.feet_to_cm(parsed['feet'], parsed['inches'])
|
| 205 |
+
return f"{result} cm"
|
| 206 |
+
elif parsed['unit'] == 'meters':
|
| 207 |
+
result = self.meters_to_cm(parsed['meters'])
|
| 208 |
+
return f"{result} cm"
|
| 209 |
+
else:
|
| 210 |
+
return f"{parsed['cm']} cm"
|
| 211 |
+
|
| 212 |
+
elif to_unit == "feet":
|
| 213 |
+
if parsed['unit'] == 'cm':
|
| 214 |
+
feet, inches = self.cm_to_feet(parsed['cm'])
|
| 215 |
+
return f"{feet}'{inches:.1f}\""
|
| 216 |
+
elif parsed['unit'] == 'meters':
|
| 217 |
+
feet, inches = self.meters_to_feet(parsed['meters'])
|
| 218 |
+
return f"{feet}'{inches:.1f}\""
|
| 219 |
+
else:
|
| 220 |
+
return f"{parsed['feet']}'{parsed['inches']:.1f}\""
|
| 221 |
+
|
| 222 |
+
elif to_unit == "meters" or to_unit == "m":
|
| 223 |
+
if parsed['unit'] == 'feet':
|
| 224 |
+
result = self.feet_to_meters(parsed['feet'], parsed['inches'])
|
| 225 |
+
return f"{result} m"
|
| 226 |
+
elif parsed['unit'] == 'cm':
|
| 227 |
+
result = self.cm_to_meters(parsed['cm'])
|
| 228 |
+
return f"{result} m"
|
| 229 |
+
else:
|
| 230 |
+
return f"{parsed['meters']} m"
|
| 231 |
+
|
| 232 |
+
else:
|
| 233 |
+
raise ValueError(f"Unknown target unit: {to_unit}")
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def main():
|
| 237 |
+
"""Command line interface for the height converter."""
|
| 238 |
+
import argparse
|
| 239 |
+
|
| 240 |
+
parser = argparse.ArgumentParser(
|
| 241 |
+
description='Convert height between different units'
|
| 242 |
+
)
|
| 243 |
+
parser.add_argument(
|
| 244 |
+
'height',
|
| 245 |
+
type=str,
|
| 246 |
+
help='Height to convert (e.g., "5\'10\"", "180cm", "1.8m")'
|
| 247 |
+
)
|
| 248 |
+
parser.add_argument(
|
| 249 |
+
'--to',
|
| 250 |
+
type=str,
|
| 251 |
+
default='cm',
|
| 252 |
+
choices=['cm', 'feet', 'meters', 'm'],
|
| 253 |
+
help='Target unit (default: cm)'
|
| 254 |
+
)
|
| 255 |
+
|
| 256 |
+
args = parser.parse_args()
|
| 257 |
+
|
| 258 |
+
converter = HeightConverter()
|
| 259 |
+
try:
|
| 260 |
+
result = converter.convert(args.height, args.to)
|
| 261 |
+
print(result)
|
| 262 |
+
except ValueError as e:
|
| 263 |
+
print(f"Error: {e}")
|
| 264 |
+
return 1
|
| 265 |
+
|
| 266 |
+
return 0
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
if __name__ == '__main__':
|
| 270 |
+
exit(main())
|
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Include base requirements
|
| 2 |
+
-r requirements.txt
|
| 3 |
+
|
| 4 |
+
# Additional development tools
|
| 5 |
+
pytest-xdist>=2.5.0 # Parallel test execution
|
| 6 |
+
pytest-mock>=3.10.0 # Mocking support
|
| 7 |
+
coverage>=6.5.0 # Code coverage
|
| 8 |
+
|
| 9 |
+
# Code quality
|
| 10 |
+
pylint>=2.15.0
|
| 11 |
+
autopep8>=2.0.0
|
| 12 |
+
isort>=5.11.0
|
| 13 |
+
|
| 14 |
+
# Type checking
|
| 15 |
+
types-click>=8.0.0
|
| 16 |
+
|
| 17 |
+
# Pre-commit hooks
|
| 18 |
+
pre-commit>=2.20.0
|
| 19 |
+
|
| 20 |
+
# Jupyter for experimentation
|
| 21 |
+
jupyter>=1.0.0
|
| 22 |
+
ipython>=8.0.0
|
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Core dependencies
|
| 2 |
+
numpy>=1.21.0
|
| 3 |
+
pandas>=1.3.0
|
| 4 |
+
|
| 5 |
+
# CLI support
|
| 6 |
+
click>=8.0.0
|
| 7 |
+
argparse>=1.4.0
|
| 8 |
+
|
| 9 |
+
# Testing
|
| 10 |
+
pytest>=7.0.0
|
| 11 |
+
pytest-cov>=3.0.0
|
| 12 |
+
|
| 13 |
+
# Development
|
| 14 |
+
black>=22.0.0
|
| 15 |
+
flake8>=4.0.0
|
| 16 |
+
mypy>=0.950
|
| 17 |
+
|
| 18 |
+
# Documentation
|
| 19 |
+
sphinx>=4.5.0
|
| 20 |
+
sphinx-rtd-theme>=1.0.0
|
| 21 |
+
|
| 22 |
+
# Optional: Web API support
|
| 23 |
+
flask>=2.0.0
|
| 24 |
+
fastapi>=0.95.0
|
| 25 |
+
uvicorn>=0.21.0
|
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Setup configuration for height-conversion-tool
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from setuptools import setup, find_packages
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
# Read the README file
|
| 9 |
+
this_directory = Path(__file__).parent
|
| 10 |
+
long_description = (this_directory / "README.md").read_text(encoding='utf-8')
|
| 11 |
+
|
| 12 |
+
setup(
|
| 13 |
+
name="height-conversion-tool",
|
| 14 |
+
version="1.0.0",
|
| 15 |
+
author="NuBest Team",
|
| 16 |
+
author_email="support@nubest.com",
|
| 17 |
+
description="A simple and efficient tool for converting height measurements between different units",
|
| 18 |
+
long_description=long_description,
|
| 19 |
+
long_description_content_type="text/markdown",
|
| 20 |
+
url="https://huggingface.co/NuBest/height-conversion-tool",
|
| 21 |
+
packages=find_packages(),
|
| 22 |
+
classifiers=[
|
| 23 |
+
"Development Status :: 4 - Beta",
|
| 24 |
+
"Intended Audience :: Developers",
|
| 25 |
+
"Intended Audience :: Healthcare Industry",
|
| 26 |
+
"Topic :: Scientific/Engineering",
|
| 27 |
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
| 28 |
+
"License :: OSI Approved :: Apache Software License",
|
| 29 |
+
"Programming Language :: Python :: 3",
|
| 30 |
+
"Programming Language :: Python :: 3.8",
|
| 31 |
+
"Programming Language :: Python :: 3.9",
|
| 32 |
+
"Programming Language :: Python :: 3.10",
|
| 33 |
+
"Programming Language :: Python :: 3.11",
|
| 34 |
+
"Operating System :: OS Independent",
|
| 35 |
+
],
|
| 36 |
+
keywords="height conversion measurement unit-converter feet inches centimeters meters",
|
| 37 |
+
python_requires=">=3.8",
|
| 38 |
+
install_requires=[
|
| 39 |
+
"numpy>=1.21.0",
|
| 40 |
+
"click>=8.0.0",
|
| 41 |
+
],
|
| 42 |
+
extras_require={
|
| 43 |
+
"dev": [
|
| 44 |
+
"pytest>=7.0.0",
|
| 45 |
+
"pytest-cov>=3.0.0",
|
| 46 |
+
"black>=22.0.0",
|
| 47 |
+
"flake8>=4.0.0",
|
| 48 |
+
"mypy>=0.950",
|
| 49 |
+
],
|
| 50 |
+
"web": [
|
| 51 |
+
"flask>=2.0.0",
|
| 52 |
+
"fastapi>=0.95.0",
|
| 53 |
+
"uvicorn>=0.21.0",
|
| 54 |
+
],
|
| 55 |
+
},
|
| 56 |
+
entry_points={
|
| 57 |
+
"console_scripts": [
|
| 58 |
+
"height-convert=height_converter:main",
|
| 59 |
+
],
|
| 60 |
+
},
|
| 61 |
+
project_urls={
|
| 62 |
+
"Bug Reports": "https://huggingface.co/NuBest/height-conversion-tool/discussions",
|
| 63 |
+
"Source": "https://huggingface.co/NuBest/height-conversion-tool",
|
| 64 |
+
"Documentation": "https://huggingface.co/NuBest/height-conversion-tool",
|
| 65 |
+
},
|
| 66 |
+
)
|
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Unit tests for HeightConverter
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import pytest
|
| 6 |
+
from height_converter import HeightConverter
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class TestHeightConverter:
|
| 10 |
+
"""Test suite for HeightConverter class."""
|
| 11 |
+
|
| 12 |
+
@pytest.fixture
|
| 13 |
+
def converter(self):
|
| 14 |
+
"""Create a HeightConverter instance for testing."""
|
| 15 |
+
return HeightConverter()
|
| 16 |
+
|
| 17 |
+
# Test feet to cm conversions
|
| 18 |
+
def test_feet_to_cm_basic(self, converter):
|
| 19 |
+
"""Test basic feet to cm conversion."""
|
| 20 |
+
result = converter.feet_to_cm(5, 10)
|
| 21 |
+
assert result == 177.8
|
| 22 |
+
|
| 23 |
+
def test_feet_to_cm_no_inches(self, converter):
|
| 24 |
+
"""Test feet to cm with no inches."""
|
| 25 |
+
result = converter.feet_to_cm(6)
|
| 26 |
+
assert result == 182.88
|
| 27 |
+
|
| 28 |
+
def test_feet_to_cm_negative(self, converter):
|
| 29 |
+
"""Test that negative values raise ValueError."""
|
| 30 |
+
with pytest.raises(ValueError):
|
| 31 |
+
converter.feet_to_cm(-5, 10)
|
| 32 |
+
|
| 33 |
+
# Test cm to feet conversions
|
| 34 |
+
def test_cm_to_feet_basic(self, converter):
|
| 35 |
+
"""Test basic cm to feet conversion."""
|
| 36 |
+
feet, inches = converter.cm_to_feet(180)
|
| 37 |
+
assert feet == 5
|
| 38 |
+
assert inches == pytest.approx(10.9, rel=0.1)
|
| 39 |
+
|
| 40 |
+
def test_cm_to_feet_short(self, converter):
|
| 41 |
+
"""Test cm to feet for shorter height."""
|
| 42 |
+
feet, inches = converter.cm_to_feet(150)
|
| 43 |
+
assert feet == 4
|
| 44 |
+
assert inches == pytest.approx(11.1, rel=0.1)
|
| 45 |
+
|
| 46 |
+
def test_cm_to_feet_negative(self, converter):
|
| 47 |
+
"""Test that negative cm raises ValueError."""
|
| 48 |
+
with pytest.raises(ValueError):
|
| 49 |
+
converter.cm_to_feet(-180)
|
| 50 |
+
|
| 51 |
+
# Test meters conversions
|
| 52 |
+
def test_meters_to_feet(self, converter):
|
| 53 |
+
"""Test meters to feet conversion."""
|
| 54 |
+
feet, inches = converter.meters_to_feet(1.75)
|
| 55 |
+
assert feet == 5
|
| 56 |
+
assert inches == pytest.approx(8.9, rel=0.1)
|
| 57 |
+
|
| 58 |
+
def test_feet_to_meters(self, converter):
|
| 59 |
+
"""Test feet to meters conversion."""
|
| 60 |
+
result = converter.feet_to_meters(6, 0)
|
| 61 |
+
assert result == 1.83
|
| 62 |
+
|
| 63 |
+
def test_cm_to_meters(self, converter):
|
| 64 |
+
"""Test cm to meters conversion."""
|
| 65 |
+
result = converter.cm_to_meters(175)
|
| 66 |
+
assert result == 1.75
|
| 67 |
+
|
| 68 |
+
def test_meters_to_cm(self, converter):
|
| 69 |
+
"""Test meters to cm conversion."""
|
| 70 |
+
result = converter.meters_to_cm(1.8)
|
| 71 |
+
assert result == 180.0
|
| 72 |
+
|
| 73 |
+
# Test string parsing
|
| 74 |
+
def test_parse_feet_inches_standard(self, converter):
|
| 75 |
+
"""Test parsing standard feet/inches format."""
|
| 76 |
+
result = converter.parse_height_string("5'10\"")
|
| 77 |
+
assert result == {'feet': 5, 'inches': 10, 'unit': 'feet'}
|
| 78 |
+
|
| 79 |
+
def test_parse_feet_inches_no_quotes(self, converter):
|
| 80 |
+
"""Test parsing feet/inches without quotes."""
|
| 81 |
+
result = converter.parse_height_string("5'10")
|
| 82 |
+
assert result == {'feet': 5, 'inches': 10, 'unit': 'feet'}
|
| 83 |
+
|
| 84 |
+
def test_parse_cm(self, converter):
|
| 85 |
+
"""Test parsing centimeters."""
|
| 86 |
+
result = converter.parse_height_string("180cm")
|
| 87 |
+
assert result == {'cm': 180.0, 'unit': 'cm'}
|
| 88 |
+
|
| 89 |
+
def test_parse_cm_with_space(self, converter):
|
| 90 |
+
"""Test parsing cm with space."""
|
| 91 |
+
result = converter.parse_height_string("180 cm")
|
| 92 |
+
assert result == {'cm': 180.0, 'unit': 'cm'}
|
| 93 |
+
|
| 94 |
+
def test_parse_meters(self, converter):
|
| 95 |
+
"""Test parsing meters."""
|
| 96 |
+
result = converter.parse_height_string("1.8m")
|
| 97 |
+
assert result == {'meters': 1.8, 'unit': 'meters'}
|
| 98 |
+
|
| 99 |
+
def test_parse_invalid_format(self, converter):
|
| 100 |
+
"""Test that invalid format raises ValueError."""
|
| 101 |
+
with pytest.raises(ValueError):
|
| 102 |
+
converter.parse_height_string("invalid")
|
| 103 |
+
|
| 104 |
+
# Test convert method
|
| 105 |
+
def test_convert_feet_to_cm(self, converter):
|
| 106 |
+
"""Test convert from feet to cm."""
|
| 107 |
+
result = converter.convert("5'10\"", "cm")
|
| 108 |
+
assert result == "177.8 cm"
|
| 109 |
+
|
| 110 |
+
def test_convert_cm_to_feet(self, converter):
|
| 111 |
+
"""Test convert from cm to feet."""
|
| 112 |
+
result = converter.convert("180cm", "feet")
|
| 113 |
+
assert "5'" in result
|
| 114 |
+
assert "10.9\"" in result
|
| 115 |
+
|
| 116 |
+
def test_convert_meters_to_cm(self, converter):
|
| 117 |
+
"""Test convert from meters to cm."""
|
| 118 |
+
result = converter.convert("1.75m", "cm")
|
| 119 |
+
assert result == "175.0 cm"
|
| 120 |
+
|
| 121 |
+
def test_convert_cm_to_meters(self, converter):
|
| 122 |
+
"""Test convert from cm to meters."""
|
| 123 |
+
result = converter.convert("180cm", "meters")
|
| 124 |
+
assert result == "1.8 m"
|
| 125 |
+
|
| 126 |
+
def test_convert_invalid_unit(self, converter):
|
| 127 |
+
"""Test that invalid target unit raises ValueError."""
|
| 128 |
+
with pytest.raises(ValueError):
|
| 129 |
+
converter.convert("180cm", "invalid")
|
| 130 |
+
|
| 131 |
+
# Edge cases
|
| 132 |
+
def test_zero_height(self, converter):
|
| 133 |
+
"""Test handling of zero height."""
|
| 134 |
+
result = converter.feet_to_cm(0, 0)
|
| 135 |
+
assert result == 0.0
|
| 136 |
+
|
| 137 |
+
def test_very_tall_height(self, converter):
|
| 138 |
+
"""Test handling of very tall height."""
|
| 139 |
+
result = converter.feet_to_cm(8, 0)
|
| 140 |
+
assert result == 243.84
|
| 141 |
+
|
| 142 |
+
def test_decimal_inches(self, converter):
|
| 143 |
+
"""Test handling of decimal inches."""
|
| 144 |
+
result = converter.feet_to_cm(5, 10.5)
|
| 145 |
+
assert result == pytest.approx(179.07, rel=0.01)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
if __name__ == '__main__':
|
| 149 |
+
pytest.main([__file__, '-v'])
|