feat: Add new calculator batches (6-10) and associated deployment/verification scripts, and update the calculator list.

This commit is contained in:
Ben
2026-02-21 01:29:19 -08:00
parent 569b11d2ea
commit d381cd6610
16 changed files with 1901 additions and 13 deletions

View File

@@ -22,6 +22,12 @@ All calculators *MUST* include the classes `calc-input` and `calc-field` on thei
}
```
### 2.2. Slug Mismatch & Duplicate Prevention
**CRITICAL**: Do not create a new post if the calculator already exists. WordPress will automatically append `-2` to the slug (e.g., `inches-to-millimeters-2`).
- **Detection**: Always perform a GET request for the intended slug before POSTing.
- **Resolution**: If a duplicate is found, capture the existing `id` and use `PUT` to update the content rather than creating a new entry.
- **Registry**: Ensure the `Id` in `calculators_list.md` matches the post serving the "clean" slug (no `-2`).
### 2.1. SEO Copy Guidelines
The SEO block appended at the end of the calculator `content` must strictly adhere to the following style:
- **Length**: Expand the text to 2-3 detailed paragraphs providing educational information on the units involved, their history, uses, and the conversion methodologies.
@@ -34,9 +40,30 @@ The JavaScript that performs the actual mathematical conversion is *detached* fr
Whenever a new calculator is created:
1. Capture the returned `id` of the published calculator.
2. Formulate the JS math conversion script wrapping events to the unique input IDs.
3. **CRITICAL: URL Parameter Support:** Ensure the script listens to the DOM `DOMContentLoaded` event and parses the `window.location.search` URL query parameters for `?v1=` (Input 1) and `?v2=` (Input 2). If present, the corresponding input must be automatically populated and the calculation function triggered.
4. Submit a new `kadence_element` POST request injecting the `<script>...</script>`.
5. Apply these required metadata values so it correctly loads on your specific calculator:
init();
})();
</script>
```
### 3.1. 3-Variable Solver Pattern (e.g., Ohm's Law)
For calculators with 3 inputs (A, B, C where A * B = C), use the "solve" function pattern to ensure reactivity:
```javascript
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
```
4. **URL Parameter Support:** Ensure the script parses `window.location.search` for `?v1=` (Input 1) and `?v2=` (Input 2).
5. Submit a new `kadence_element` POST request injecting the `<script>...</script>`.
6. Apply these required metadata values:
- `_kad_element_hook`: `kadence_after_header`
- `_kad_element_show_conditionals`: `'[{"rule":"singular|calculator","select":"ids","ids":[<CALCULATOR_POST_ID>],"mustMatch":false}]'`
@@ -46,6 +73,7 @@ After the Kadence Element is injected and the calculator is live, **you must ver
2. Execute an HTTP/URL request simulating the Unit A input (e.g., `?v1=1`) and verify the output accurately reflects Unit B.
3. Reverse the test: simulate the Unit B input (e.g., `?v2=2.54`) and verify the output accurately reflects Unit A.
4. If either math direction fails or produces precision floating-point inaccuracies, you must correct the Kadence Element JavaScript block.
5. **Live Logic Audit**: View the page source and search for `<!-- [element-ID] -->`. Ensure the ID matches the one in the registry and contains the robust `init` pattern.
## 4. Calculator Registry
To avoid unnecessary scraping of the REST API, immediately update the `calculators_list.md` file located in the workspace directory with the details (Title, Post ID, Kadence Element ID) upon successful deployment.

60
audit_mapping.py Normal file
View File

@@ -0,0 +1,60 @@
import urllib.request
import json
import base64
import time
import re
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element"
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
def get_all(url):
results = []
page = 1
while True:
req = urllib.request.Request(f"{url}?per_page=100&page={page}", headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30)
data = json.loads(resp.read().decode("utf-8"))
if not data: break
results.extend(data)
page += 1
except:
break
return results
print("Fetching all calculators...")
calcs = get_all(url_base_calc)
calc_map = {c['id']: c['slug'] for c in calcs}
print("Fetching all elements...")
elements = get_all(url_base_kadence)
mapping = []
for e in elements:
meta = e.get('meta', {})
cond = meta.get('_kad_element_show_conditionals', '')
if cond:
try:
cond_data = json.loads(cond)
if isinstance(cond_data, list) and len(cond_data) > 0:
ids = cond_data[0].get('ids', [])
for pid in ids:
if pid in calc_map:
mapping.append({
'eid': e['id'],
'pid': pid,
'slug': calc_map[pid],
'title': e['title']['rendered']
})
except:
continue
with open("/tmp/element_mapping.json", "w") as f:
json.dump(mapping, f, indent=2)
print(f"Found {len(mapping)} mappings.")

146
batch_10.py Normal file
View File

@@ -0,0 +1,146 @@
import urllib.request
import json
import base64
import time
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
batch_10 = [
{"title": "Megabytes to Gigabytes", "slug": "megabytes-to-gigabytes", "v1": "Megabytes (MB)", "v2": "Gigabytes (GB)", "factor": 0.001, "desc": "One gigabyte contains 1,000 megabytes (decimal definition). This conversion is standard in consumer electronics and storage capacity reporting."},
{"title": "Megajoules to Kilowatt-hours", "slug": "megajoules-to-kilowatt-hours", "v1": "Megajoules (MJ)", "v2": "Kilowatt-hours (kWh)", "factor": 0.277778, "desc": "One kilowatt-hour is exactly 3.6 megajoules. Megajoules are often used in scientific energy calculations, while kWh is the standard for utility billing."},
{"title": "Meters to Feet", "slug": "meters-to-feet", "v1": "Meters (m)", "v2": "Feet (ft)", "factor": 3.28084, "desc": "The meter is the SI base unit of length. One meter is approximately 3.28 feet, a common conversion for height and room dimensions."},
{"title": "Meters to Yards", "slug": "meters-to-yards", "v1": "Meters (m)", "v2": "Yards (yd)", "factor": 1.09361, "desc": "Meters and yards are similar in scale, but the meter is slightly longer (approx. 1.09 yards). This is common in sports like swimming and athletics."},
{"title": "Metric tons to Short tons", "slug": "metric-tons-to-short-tons", "v1": "Metric Tons (t)", "v2": "Short Tons (US)", "factor": 1.10231, "desc": "A metric ton (tonne) is 1,000 kg, slightly heavier than the US short ton (2,000 lbs)."},
{"title": "Minutes to Hours", "slug": "minutes-to-hours", "v1": "Minutes (min)", "v2": "Hours (hr)", "factor": 0.0166667, "desc": "Sixty minutes make one hour. This conversion is used for tracking labor hours and travel duration."},
{"title": "Minutes to Seconds", "slug": "minutes-to-seconds", "v1": "Minutes (min)", "v2": "Seconds (s)", "factor": 60.0, "desc": "One minute contains sixty seconds. This conversion is essential for high-precision time tracking and performance measurement."},
{"title": "Nautical miles to Kilometers", "slug": "nautical-miles-to-kilometers", "v1": "Nautical Miles (nmi)", "v2": "Kilometers (km)", "factor": 1.852, "desc": "A nautical mile is defined based on the Earth's circumference and is exactly 1.852 kilometers, the standard for maritime and aviation navigation."},
{"title": "Newtons to Dynes", "slug": "newtons-to-dynes", "v1": "Newtons (N)", "v2": "Dynes (dyn)", "factor": 100000.0, "desc": "A newton is the SI unit of force. One newton is equal to 100,000 dynes (the CGS unit of force)."},
{"title": "Ounces to Grams", "slug": "ounces-to-grams", "v1": "Ounces (oz)", "v2": "Grams (g)", "factor": 28.3495, "desc": "One avoirdupois ounce is approximately 28.35 grams. This is the global standard for kitchen measurements and postal weights."}
]
def check_exists(slug):
req = urllib.request.Request(f"{url_base_calc}?slug={slug}", headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30)
data = json.loads(resp.read().decode("utf-8"))
if data: return data[0]['id']
except: pass
return None
def get_element_id_for_post(post_id):
req_e = urllib.request.Request(f"{url_base_kadence}?per_page=100", headers=headers)
try:
resp_e = urllib.request.urlopen(req_e, timeout=30)
elements = json.loads(resp_e.read().decode("utf-8"))
for e in elements:
cond = e.get('meta', {}).get('_kad_element_show_conditionals', '')
if str(post_id) in cond:
return e['id']
except: pass
return None
for item in batch_10:
print(f"\n--- Processing {item['title']} ---")
slug = item['slug']
unique_id = slug.replace('-', '_')
calc_html = f"""
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_row","columns":1,"colLayout":"equal","maxWidth":600,"bgColor":"#f5f7f9","borderRadius":8,"padding":[32,32,32,32],"marginUnit":"px"}} -->
<div class="wp-block-kadence-rowlayout alignnone"><div class="kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top" style="background-color:#f5f7f9;border-radius:8px;padding:2rem;">
<!-- wp:kadence/column {{"uniqueID":"{unique_id}_col"}} -->
<div class="wp-block-kadence-column"><div class="kt-inside-inner-col">
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_inner_row","columns":2,"colLayout":"equal","maxWidth":600,"marginUnit":"px"}} -->
<div class="kb-row-layout-wrap kb-row-layout-id_{unique_id}_row aligncenter wp-block-kadence-rowlayout"><div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">
<div class="wp-block-kadence-column kadence-column_{unique_id}_col1"><div class="kt-inside-inner-col">
<label for="input-1" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v1']}</label>
<input type="number" id="input-1" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div>
<div class="wp-block-kadence-column kadence-column_{unique_id}_col2"><div class="kt-inside-inner-col">
<label for="input-2" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v2']}</label>
<input type="number" id="input-2" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div></div></div>
</div></div>
<!-- /wp:kadence/column -->
</div></div>
<!-- /wp:kadence/rowlayout -->
<p style="margin-top: 2rem; line-height: 1.6;">{item['desc']}</p>
"""
existing_id = check_exists(slug)
if existing_id:
print(f"--> Updating existing calculator (ID: {existing_id})")
calc_data = {"content": calc_html, "title": item['title']}
req_c = urllib.request.Request(f"{url_base_calc}/{existing_id}", data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="PUT")
post_id = existing_id
else:
print(f"--> Creating new calculator")
calc_data = {"title": item['title'], "slug": slug, "status": "publish", "content": calc_html}
req_c = urllib.request.Request(url_base_calc, data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="POST")
resp_c = urllib.request.urlopen(req_c, timeout=30)
post_id = json.loads(resp_c.read().decode("utf-8"))['id']
# Robust JS Logic
js_logic = f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {item['factor']}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat((v / {item['factor']}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
element_id = get_element_id_for_post(post_id)
if element_id:
print(f"--> Updating existing JS Logic element (ID: {element_id})")
kadence_data = {"content": js_logic}
req_j = urllib.request.Request(f"{url_base_kadence}/{element_id}", data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="PUT")
else:
print(f"--> Creating new JS Logic element")
kadence_data = {
"title": f"JS Logic: {item['title']}",
"status": "publish",
"content": js_logic,
"meta": {
"_kad_element_hook": "kadence_after_header",
"_kad_element_show_conditionals": json.dumps([{"rule": "singular|calculator", "select": "ids", "ids": [post_id], "mustMatch": False}])
}
}
req_j = urllib.request.Request(url_base_kadence, data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="POST")
urllib.request.urlopen(req_j, timeout=30)
print(f"--> SUCCESS: Post {post_id}")
time.sleep(1)
print("\nBATCH 10 COMPLETE")

247
batch_6.py Normal file
View File

@@ -0,0 +1,247 @@
import urllib.request
import json
import base64
import time
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator/"
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element/"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
batch_6 = [
{
"title": "Grams to Apothecary Ounces",
"slug": "grams-to-apothecary-ounces",
"label1": "Grams (g)",
"label2": "Apothecary Ounces (ap oz)",
"factor": 0.0321507466,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Weight Conversion:</strong> Apothecary ounces were historically used by pharmacists and chemists to measure ingredients for medicine. This calculator provides a precise conversion to standard metric grams.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Grams to Carats",
"slug": "grams-to-carats",
"label1": "Grams (g)",
"label2": "Carats (ct)",
"factor": 5.0,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Jewelry Weight:</strong> The metric carat is defined as exactly 200 milligrams. Converting grams to carats is standard practice in the gemstone industry for pricing and weight measurement.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Grams to Grains",
"slug": "grams-to-grains",
"label1": "Grams (g)",
"label2": "Grains (gr)",
"factor": 15.4323584,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Fine Weight:</strong> One gram is equivalent to approximately 15.43 grains. Grains are used in various specialized fields, including the measurement of gunpowder and certain medications.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Horsepower to Kilowatts",
"slug": "horsepower-to-kilowatts",
"label1": "Horsepower (hp)",
"label2": "Kilowatts (kW)",
"factor": 0.745699872,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Power Measurement:</strong> Horsepower is a unit used to measure the power of engines and motors. Converting to kilowatts (the SI unit) allows for easier comparison across different engineering standards.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Hours to Days",
"slug": "hours-to-days",
"label1": "Hours",
"label2": "Days",
"factor": 0.0416666667,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Time Management:</strong> There are exactly 24 hours in one day. This tool facilitates the conversion of hourly task durations or logistical windows into full day equivalents.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Hours to Minutes",
"slug": "hours-to-minutes",
"label1": "Hours",
"label2": "Minutes",
"factor": 60.0,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Quick Time Math:</strong> Converting hours into minutes is one of the most common everyday calculations for scheduling, travel, and logistics.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Inches of Mercury to Pascals",
"slug": "inches-of-mercury-to-pascals",
"label1": "Inches of Mercury (inHg)",
"label2": "Pascals (Pa)",
"factor": 3386.389,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Pressure Conversion:</strong> Inches of mercury is a unit for pressure used in meteorology and aviation. Converting to pascals (the SI unit) is necessary for various scientific and atmospheric calculations.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Inches of Water to Pascals",
"slug": "inches-of-water-to-pascals",
"label1": "Inches of Water (inH2O)",
"label2": "Pascals (Pa)",
"factor": 249.08891,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>HVAC & Fluid Dynamics:</strong> Inches of water column (WC) is a unit commonly used in low-pressure applications like ventilation and plumbing systems. One inch of water is approximately 249 pascals.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Inches to Centimeters",
"slug": "inches-to-centimeters",
"label1": "Inches (in)",
"label2": "Centimeters (cm)",
"factor": 2.54,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Metric Precision:</strong> The international inch is defined as exactly 2.54 centimeters. This converter is used daily for manufacturing, design, and education worldwide.</p>
<!-- /wp:paragraph -->
"""
},
{
"title": "Inches to Millimeters",
"slug": "inches-to-millimeters",
"label1": "Inches (in)",
"label2": "Millimeters (mm)",
"factor": 25.4,
"offset": 0,
"seo_text": """
<!-- wp:paragraph -->
<p style="margin-top: 2rem; line-height: 1.6;"><strong>Fine Precision:</strong> Millimeters offer a finer grain of measurement for technical drawings and engineering. One inch equals exactly 25.4 millimeters.</p>
<!-- /wp:paragraph -->
"""
}
]
for item in batch_6[4:]:
print(f"\\n--- Processing {item['title']} ---")
slug_raw = item['slug'].replace("-", "")
content_html = f"""
<!-- wp:kadence/rowlayout {{"uniqueID":"{item['slug']}_outer","bgColor":"#f5f7f9","padding":["2rem","2rem","2rem","2rem"],"borderRadius":["8px","8px","8px","8px"]}} -->
<div class="wp-block-kadence-rowlayout alignnone"><div class="kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top" style="background-color:#f5f7f9;border-radius:8px;padding:2rem;">
<!-- wp:kadence/column {{"uniqueID":"{item['slug']}_inner"}} -->
<div class="wp-block-kadence-column"><div class="kt-inside-inner-col">
<style>.kb-row-layout-id_{slug_raw}_row > .kt-row-column-wrap{{align-content:start;}}:where(.kb-row-layout-id_{slug_raw}_row > .kt-row-column-wrap) > .wp-block-kadence-column{{justify-content:start;}}.kb-row-layout-id_{slug_raw}_row > .kt-row-column-wrap{{column-gap:var(--global-kb-gap-md, 2rem);row-gap:var(--global-kb-gap-md, 2rem);max-width:600px;margin-left:auto;margin-right:auto;grid-template-columns:repeat(2, minmax(0, 1fr));}}.kb-row-layout-id_{slug_raw}_row > .kt-row-layout-overlay{{opacity:0.30;}}@media all and (max-width: 1024px){{.kb-row-layout-id_{slug_raw}_row > .kt-row-column-wrap{{grid-template-columns:repeat(2, minmax(0, 1fr));}}}}@media all and (max-width: 767px){{.kb-row-layout-id_{slug_raw}_row > .kt-row-column-wrap{{grid-template-columns:minmax(0, 1fr);}}}}</style><div class="kb-row-layout-wrap kb-row-layout-id_{slug_raw}_row aligncenter wp-block-kadence-rowlayout"><div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">
<div class="wp-block-kadence-column kadence-column_{slug_raw}_col1"><div class="kt-inside-inner-col">
<label for="input-1" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['label1']}</label>
<input type="number" id="input-1" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div>
<div class="wp-block-kadence-column kadence-column_{slug_raw}_col2"><div class="kt-inside-inner-col">
<label for="input-2" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['label2']}</label>
<input type="number" id="input-2" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div></div></div>
</div></div>
<!-- /wp:kadence/column -->
</div></div>
<!-- /wp:kadence/rowlayout -->
{item['seo_text']}
"""
calc_data = {
"title": item['title'],
"status": "publish",
"slug": item['slug'],
"content": content_html,
"format": "standard"
}
# Post Calculator
req_c = urllib.request.Request(url_base_calc, data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="POST")
try:
resp_c = urllib.request.urlopen(req_c, timeout=30)
res_c = json.loads(resp_c.read().decode("utf-8"))
post_id = res_c['id']
print(f"--> Posted {item['title']} (ID: {post_id})")
# JS Logic with robust event handling
offset = item.get('offset', 0)
js_wrapped = f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.r < 50) {{
window.r++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {item['factor']} + {offset}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat(((v - {offset}) / {item['factor']}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
window.r = 0;
init();
}})();
</script>"""
kadence_data = {
"title": f"JS Logic: {item['title']}",
"status": "publish",
"content": js_wrapped,
"meta": {
"_kad_element_hook": "kadence_after_header",
"_kad_element_show_conditionals": json.dumps([{"rule": "singular|calculator", "select": "ids", "ids": [post_id], "mustMatch": False}])
}
}
req_j = urllib.request.Request(url_base_kadence, data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="POST")
urllib.request.urlopen(req_j, timeout=30)
print(f"--> Posted JS hook")
except Exception as e:
print(f"Error: {e}")
if hasattr(e, 'read'): print(e.read().decode('utf-8'))
time.sleep(1)
print("\\n--- BATCH 6 COMPLETE ---")

142
batch_7.py Normal file
View File

@@ -0,0 +1,142 @@
import urllib.request
import json
import base64
import time
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
batch_7 = [
{"title": "Centigrams to Grams", "slug": "centigrams-to-grams", "v1": "Centigrams (cg)", "v2": "Grams (g)", "factor": 0.01, "desc": "Centigrams are a metric unit of mass equal to 1/100th of a gram. They are used in chemistry and pharmacy for small measurements."},
{"title": "Centiliters to Liters", "slug": "centiliters-to-liters", "v1": "Centiliters (cl)", "v2": "Liters (l)", "factor": 0.01, "desc": "Centiliters are commonly used in Europe for measuring liquid volumes in beverages. One centiliter is 10 milliliters."},
{"title": "Centimeters to Feet", "slug": "centimeters-to-feet", "v1": "Centimeters (cm)", "v2": "Feet (ft)", "factor": 0.032808399, "desc": "Centimeters are the standard metric unit for length in everyday use, while feet remain prevalent in the US and UK for height and construction."},
{"title": "Centimeters to Meters", "slug": "centimeters-to-meters", "v1": "Centimeters (cm)", "v2": "Meters (m)", "factor": 0.01, "desc": "The meter is the base unit of length in the International System of Units (SI). There are exactly 100 centimeters in one meter."},
{"title": "Centimeters to Millimeters", "slug": "centimeters-to-millimeters", "v1": "Centimeters (cm)", "v2": "Millimeters (mm)", "factor": 10.0, "desc": "Millimeters provide higher precision for small-scale measurements. One centimeter consists of ten millimeters."},
{"title": "Chains to Feet", "slug": "chains-to-feet", "v1": "Chains (ch)", "v2": "Feet (ft)", "factor": 66.0, "desc": "A chain is a unit of length equal to 66 feet, historically used in land surveying and railway engineering (Gunter's chain)."},
{"title": "Chains to Meters", "slug": "chains-to-meters", "v1": "Chains (ch)", "v2": "Meters (m)", "factor": 20.1168, "desc": "In modern surveying, the traditional chain (66 feet) is defined as exactly 20.1168 meters."},
{"title": "Cubic Centimeters to Cubic Inches", "slug": "cubic-centimeters-to-cubic-inches", "v1": "Cubic Centimeters (cc)", "v2": "Cubic Inches (cu in)", "factor": 0.0610237441, "desc": "Cubic centimeters (cc) are equal to milliliters and are often used to measure engine displacement."},
{"title": "Cubic Feet to Cubic Meters", "slug": "cubic-feet-to-cubic-meters", "v1": "Cubic Feet (cu ft)", "v2": "Cubic Meters (m³)", "factor": 0.0283168466, "desc": "Cubic feet are used for shipping volumes and HVAC capacity, while cubic meters are the metric standard for volume."},
{"title": "Cubic Meters to Liters", "slug": "cubic-meters-to-liters", "v1": "Cubic Meters (m³)", "v2": "Liters (l)", "factor": 1000.0, "desc": "A cubic meter is a large unit of volume equal to one thousand liters, often used for water consumption or industrial reservoirs."}
]
def check_exists(slug):
req = urllib.request.Request(f"{url_base_calc}?slug={slug}", headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30)
data = json.loads(resp.read().decode("utf-8"))
if data: return data[0]['id']
except: pass
return None
for item in batch_7:
print(f"\n--- Processing {item['title']} ---")
calc_html = f"""
<!-- wp:kadence/rowlayout {{"uniqueID":"{item['slug'].replace('-','')}_row","columns":1,"colLayout":"equal","maxWidth":600,"bgColor":"#f5f7f9","borderRadius":8,"padding":[32,32,32,32],"marginUnit":"px"}} -->
<div class="wp-block-kadence-rowlayout alignnone"><div class="kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top" style="background-color:#f5f7f9;border-radius:8px;padding:2rem;">
<!-- wp:kadence/column {{"uniqueID":"{item['slug'].replace('-','')}_col"}} -->
<div class="wp-block-kadence-column"><div class="kt-inside-inner-col">
<!-- wp:kadence/rowlayout {{"uniqueID":"{item['slug'].replace('-','')}_inner_row","columns":2,"colLayout":"equal","maxWidth":600,"marginUnit":"px"}} -->
<div class="kb-row-layout-wrap kb-row-layout-id_{item['slug'].replace('-','')}_row aligncenter wp-block-kadence-rowlayout"><div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">
<div class="wp-block-kadence-column kadence-column_{item['slug'].replace('-','')}_col1"><div class="kt-inside-inner-col">
<label for="input-1" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v1']}</label>
<input type="number" id="input-1" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div>
<div class="wp-block-kadence-column kadence-column_{item['slug'].replace('-','')}_col2"><div class="kt-inside-inner-col">
<label for="input-2" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v2']}</label>
<input type="number" id="input-2" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div></div></div>
</div></div>
<!-- /wp:kadence/column -->
</div></div>
<!-- /wp:kadence/rowlayout -->
<p style="margin-top: 2rem; line-height: 1.6;">{item['desc']}</p>
"""
existing_id = check_exists(item['slug'])
if existing_id:
print(f"--> Updating existing calculator (ID: {existing_id})")
calc_data = {"content": calc_html, "title": item['title']}
req_c = urllib.request.Request(f"{url_base_calc}/{existing_id}", data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="PUT")
post_id = existing_id
else:
print(f"--> Creating new calculator")
calc_data = {"title": item['title'], "slug": item['slug'], "status": "publish", "content": calc_html}
req_c = urllib.request.Request(url_base_calc, data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="POST")
resp_c = urllib.request.urlopen(req_c, timeout=30)
post_id = json.loads(resp_c.read().decode("utf-8"))['id']
# Robust JS Logic
js_logic = f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {item['factor']}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat((v / {item['factor']}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
# Check for existing Kadence element targeted at this post_id
req_e = urllib.request.Request(f"{url_base_kadence}?per_page=100", headers=headers)
resp_e = urllib.request.urlopen(req_e, timeout=30)
elements = json.loads(resp_e.read().decode("utf-8"))
element_id = None
for e in elements:
cond = e.get('meta', {}).get('_kad_element_show_conditionals', '')
if str(post_id) in cond:
element_id = e['id']
break
if element_id:
print(f"--> Updating existing JS Logic element (ID: {element_id})")
kadence_data = {"content": js_logic}
req_j = urllib.request.Request(f"{url_base_kadence}/{element_id}", data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="PUT")
else:
print(f"--> Creating new JS Logic element")
kadence_data = {
"title": f"JS Logic: {item['title']}",
"status": "publish",
"content": js_logic,
"meta": {
"_kad_element_hook": "kadence_after_header",
"_kad_element_show_conditionals": json.dumps([{"rule": "singular|calculator", "select": "ids", "ids": [post_id], "mustMatch": False}])
}
}
req_j = urllib.request.Request(url_base_kadence, data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="POST")
urllib.request.urlopen(req_j, timeout=30)
print(f"--> SUCCESS: Post {post_id}")
time.sleep(1)
print("\nBATCH 7 COMPLETE")

146
batch_8.py Normal file
View File

@@ -0,0 +1,146 @@
import urllib.request
import json
import base64
import time
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
batch_8 = [
{"title": "Grams to Micrograms", "slug": "grams-to-micrograms", "v1": "Grams (g)", "v2": "Micrograms (µg)", "factor": 1000000.0, "desc": "A gram is a basic unit of mass in the metric system. A microgram is one-millionth of a gram, used primarily in medicine and micro-biology."},
{"title": "Grams to Milligrams", "slug": "grams-to-milligrams", "v1": "Grams (g)", "v2": "Milligrams (mg)", "factor": 1000.0, "desc": "One gram equals one thousand milligrams. This conversion is extremely common across science, medication dosage, and dietary tracking."},
{"title": "Hectopascals to Pascals", "slug": "hectopascals-to-pascals", "v1": "Hectopascals (hPa)", "v2": "Pascals (Pa)", "factor": 100.0, "desc": "The pascal (Pa) is the SI unit of pressure. A hectopascal is 100 pascals and is identical to the millibar, frequently used in meteorology."},
{"title": "Hectopascals to Millibars", "slug": "hectopascals-to-millibars", "v1": "Hectopascals (hPa)", "v2": "Millibars (mbar)", "factor": 1.0, "desc": "Hectopascals and millibars are equivalent units of pressure. While hectopascals are the SI standard, millibars are still widely used in weather reporting."},
{"title": "Joules to Kilojoules", "slug": "joules-to-kilojoules", "v1": "Joules (J)", "v2": "Kilojoules (kJ)", "factor": 0.001, "desc": "The joule is the SI unit of energy. One kilojoule is one thousand joules, often used for representing energy content in food or mechanical work."},
{"title": "Kilojoules to Joules", "slug": "kilojoules-to-joules", "v1": "Kilojoules (kJ)", "v2": "Joules (J)", "factor": 1000.0, "desc": "Kilojoules are larger units of energy. To convert them to standard joules, simply multiply by one thousand."},
{"title": "Micrograms to Grams", "slug": "micrograms-to-grams", "v1": "Micrograms (µg)", "v2": "Grams (g)", "factor": 0.000001, "desc": "Converting micrograms to grams is common in analytical chemistry where high-precision measurements of trace substances are required."},
{"title": "Milligrams to Grams", "slug": "milligrams-to-grams", "v1": "Milligrams (mg)", "v2": "Grams (g)", "factor": 0.001, "desc": "Milligrams are often used for small measurements of mass. One milligram is one-thousandth of a gram."},
{"title": "Millibars to Pascals", "slug": "millibars-to-pascals", "v1": "Millibars (mbar)", "v2": "Pascals (Pa)", "factor": 100.0, "desc": "One millibar is exactly 100 pascals. This relationship is a cornerstone of barometric pressure reporting in aviation and meteorology."},
{"title": "Millimeters of Mercury to Pascals", "slug": "millimeters-of-mercury-to-pascals", "v1": "mmHg", "v2": "Pascals (Pa)", "factor": 133.322, "desc": "Millimeters of mercury (mmHg) is a legacy unit of pressure, famously used for blood pressure readings. One mmHg is approximately 133.322 pascals."}
]
def check_exists(slug):
req = urllib.request.Request(f"{url_base_calc}?slug={slug}", headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30)
data = json.loads(resp.read().decode("utf-8"))
if data: return data[0]['id']
except: pass
return None
def get_element_id_for_post(post_id):
req_e = urllib.request.Request(f"{url_base_kadence}?per_page=100", headers=headers)
try:
resp_e = urllib.request.urlopen(req_e, timeout=30)
elements = json.loads(resp_e.read().decode("utf-8"))
for e in elements:
cond = e.get('meta', {}).get('_kad_element_show_conditionals', '')
if str(post_id) in cond:
return e['id']
except: pass
return None
for item in batch_8:
print(f"\n--- Processing {item['title']} ---")
slug = item['slug']
unique_id = slug.replace('-', '_')
calc_html = f"""
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_row","columns":1,"colLayout":"equal","maxWidth":600,"bgColor":"#f5f7f9","borderRadius":8,"padding":[32,32,32,32],"marginUnit":"px"}} -->
<div class="wp-block-kadence-rowlayout alignnone"><div class="kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top" style="background-color:#f5f7f9;border-radius:8px;padding:2rem;">
<!-- wp:kadence/column {{"uniqueID":"{unique_id}_col"}} -->
<div class="wp-block-kadence-column"><div class="kt-inside-inner-col">
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_inner_row","columns":2,"colLayout":"equal","maxWidth":600,"marginUnit":"px"}} -->
<div class="kb-row-layout-wrap kb-row-layout-id_{unique_id}_row aligncenter wp-block-kadence-rowlayout"><div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">
<div class="wp-block-kadence-column kadence-column_{unique_id}_col1"><div class="kt-inside-inner-col">
<label for="input-1" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v1']}</label>
<input type="number" id="input-1" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div>
<div class="wp-block-kadence-column kadence-column_{unique_id}_col2"><div class="kt-inside-inner-col">
<label for="input-2" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v2']}</label>
<input type="number" id="input-2" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div></div></div>
</div></div>
<!-- /wp:kadence/column -->
</div></div>
<!-- /wp:kadence/rowlayout -->
<p style="margin-top: 2rem; line-height: 1.6;">{item['desc']}</p>
"""
existing_id = check_exists(slug)
if existing_id:
print(f"--> Updating existing calculator (ID: {existing_id})")
calc_data = {"content": calc_html, "title": item['title']}
req_c = urllib.request.Request(f"{url_base_calc}/{existing_id}", data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="PUT")
post_id = existing_id
else:
print(f"--> Creating new calculator")
calc_data = {"title": item['title'], "slug": slug, "status": "publish", "content": calc_html}
req_c = urllib.request.Request(url_base_calc, data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="POST")
resp_c = urllib.request.urlopen(req_c, timeout=30)
post_id = json.loads(resp_c.read().decode("utf-8"))['id']
# Robust JS Logic
js_logic = f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {item['factor']}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat((v / {item['factor']}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
element_id = get_element_id_for_post(post_id)
if element_id:
print(f"--> Updating existing JS Logic element (ID: {element_id})")
kadence_data = {"content": js_logic}
req_j = urllib.request.Request(f"{url_base_kadence}/{element_id}", data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="PUT")
else:
print(f"--> Creating new JS Logic element")
kadence_data = {
"title": f"JS Logic: {item['title']}",
"status": "publish",
"content": js_logic,
"meta": {
"_kad_element_hook": "kadence_after_header",
"_kad_element_show_conditionals": json.dumps([{"rule": "singular|calculator", "select": "ids", "ids": [post_id], "mustMatch": False}])
}
}
req_j = urllib.request.Request(url_base_kadence, data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="POST")
urllib.request.urlopen(req_j, timeout=30)
print(f"--> SUCCESS: Post {post_id}")
time.sleep(1)
print("\nBATCH 8 COMPLETE")

146
batch_9.py Normal file
View File

@@ -0,0 +1,146 @@
import urllib.request
import json
import base64
import time
url_base_calc = "https://howdoyouconvert.com/wp-json/wp/v2/calculator"
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
batch_9 = [
{"title": "Meters per second to Feet per second", "slug": "meters-per-second-to-feet-per-second", "v1": "m/s", "v2": "ft/s", "factor": 3.28084, "desc": "Meters per second is the SI unit of speed. Feet per second is commonly used in aerospace and ballistics in the United States."},
{"title": "Meters per second to Miles per hour", "slug": "meters-per-second-to-miles-per-hour", "v1": "m/s", "v2": "mph", "factor": 2.23694, "desc": "This conversion is vital for understanding scientific measurements in terms of everyday vehicle speeds used in the USA and UK."},
{"title": "Meters per second to Yards per second", "slug": "meters-per-second-to-yards-per-second", "v1": "m/s", "v2": "yd/s", "factor": 1.09361, "desc": "Meters and yards are nearly equal in length, but the conversion is necessary for sports and construction where exact yardage is required."},
{"title": "Micrograms to Milligrams", "slug": "micrograms-to-milligrams", "v1": "µg", "v2": "mg", "factor": 0.001, "desc": "Both units measure very small masses. One milligram contains one thousand micrograms, a critical distinction in pharmacy and biochemistry."},
{"title": "Micrometers to Millimeters", "slug": "micrometers-to-millimeters", "v1": "µm", "v2": "mm", "factor": 0.001, "desc": "The micrometer, often called the micron, is 1/1000th of a millimeter. It is used to measure the thickness of human hair or paper."},
{"title": "Milligrams to Micrograms", "slug": "milligrams-to-micrograms", "v1": "mg", "v2": "µg", "factor": 1000.0, "desc": "Standard conversion for high-potency supplements and medicines where doses are often specified in micrograms."},
{"title": "Milliliters to Liters", "slug": "milliliters-to-liters", "v1": "ml", "v2": "l", "factor": 0.001, "desc": "The milliliter is equal to one cubic centimeter. One thousand milliliters make up one standard liter."},
{"title": "Milliliters to Fluid Ounces", "slug": "milliliters-to-fluid-ounces", "v1": "ml", "v2": "fl oz", "factor": 0.033814, "desc": "A common conversion for beverage containers and nutrition labels, translating metric milliliters to US customary fluid ounces."},
{"title": "Millimeters to Centimeters", "slug": "millimeters-to-centimeters", "v1": "mm", "v2": "cm", "factor": 0.1, "desc": "One centimeter is exactly ten millimeters. This simple metric shift is fundamental in engineering and design."},
{"title": "Millimeters to Inches", "slug": "millimeters-to-inches", "v1": "mm", "v2": "in", "factor": 0.0393701, "desc": "One inch is exactly 25.4 millimeters. This conversion is the bridge between metric and imperial precision engineering."}
]
def check_exists(slug):
req = urllib.request.Request(f"{url_base_calc}?slug={slug}", headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30)
data = json.loads(resp.read().decode("utf-8"))
if data: return data[0]['id']
except: pass
return None
def get_element_id_for_post(post_id):
req_e = urllib.request.Request(f"{url_base_kadence}?per_page=100", headers=headers)
try:
resp_e = urllib.request.urlopen(req_e, timeout=30)
elements = json.loads(resp_e.read().decode("utf-8"))
for e in elements:
cond = e.get('meta', {}).get('_kad_element_show_conditionals', '')
if str(post_id) in cond:
return e['id']
except: pass
return None
for item in batch_9:
print(f"\n--- Processing {item['title']} ---")
slug = item['slug']
unique_id = slug.replace('-', '_')
calc_html = f"""
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_row","columns":1,"colLayout":"equal","maxWidth":600,"bgColor":"#f5f7f9","borderRadius":8,"padding":[32,32,32,32],"marginUnit":"px"}} -->
<div class="wp-block-kadence-rowlayout alignnone"><div class="kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top" style="background-color:#f5f7f9;border-radius:8px;padding:2rem;">
<!-- wp:kadence/column {{"uniqueID":"{unique_id}_col"}} -->
<div class="wp-block-kadence-column"><div class="kt-inside-inner-col">
<!-- wp:kadence/rowlayout {{"uniqueID":"{unique_id}_inner_row","columns":2,"colLayout":"equal","maxWidth":600,"marginUnit":"px"}} -->
<div class="kb-row-layout-wrap kb-row-layout-id_{unique_id}_row aligncenter wp-block-kadence-rowlayout"><div class="kt-row-column-wrap kt-has-2-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top">
<div class="wp-block-kadence-column kadence-column_{unique_id}_col1"><div class="kt-inside-inner-col">
<label for="input-1" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v1']}</label>
<input type="number" id="input-1" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div>
<div class="wp-block-kadence-column kadence-column_{unique_id}_col2"><div class="kt-inside-inner-col">
<label for="input-2" style="font-weight: 600; color: #333333; margin-bottom: 8px; display: block;">{item['v2']}</label>
<input type="number" id="input-2" class="calc-input" placeholder="0" style="width:100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1.2rem;">
</div></div></div></div>
</div></div>
<!-- /wp:kadence/column -->
</div></div>
<!-- /wp:kadence/rowlayout -->
<p style="margin-top: 2rem; line-height: 1.6;">{item['desc']}</p>
"""
existing_id = check_exists(slug)
if existing_id:
print(f"--> Updating existing calculator (ID: {existing_id})")
calc_data = {"content": calc_html, "title": item['title']}
req_c = urllib.request.Request(f"{url_base_calc}/{existing_id}", data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="PUT")
post_id = existing_id
else:
print(f"--> Creating new calculator")
calc_data = {"title": item['title'], "slug": slug, "status": "publish", "content": calc_html}
req_c = urllib.request.Request(url_base_calc, data=json.dumps(calc_data).encode("utf-8"), headers=headers, method="POST")
resp_c = urllib.request.urlopen(req_c, timeout=30)
post_id = json.loads(resp_c.read().decode("utf-8"))['id']
# Robust JS Logic
js_logic = f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {item['factor']}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat((v / {item['factor']}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
element_id = get_element_id_for_post(post_id)
if element_id:
print(f"--> Updating existing JS Logic element (ID: {element_id})")
kadence_data = {"content": js_logic}
req_j = urllib.request.Request(f"{url_base_kadence}/{element_id}", data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="PUT")
else:
print(f"--> Creating new JS Logic element")
kadence_data = {
"title": f"JS Logic: {item['title']}",
"status": "publish",
"content": js_logic,
"meta": {
"_kad_element_hook": "kadence_after_header",
"_kad_element_show_conditionals": json.dumps([{"rule": "singular|calculator", "select": "ids", "ids": [post_id], "mustMatch": False}])
}
}
req_j = urllib.request.Request(url_base_kadence, data=json.dumps(kadence_data).encode("utf-8"), headers=headers, method="POST")
urllib.request.urlopen(req_j, timeout=30)
print(f"--> SUCCESS: Post {post_id}")
time.sleep(1)
print("\nBATCH 9 COMPLETE")

View File

@@ -29,7 +29,7 @@ Whenever a new calculator is published via the REST API, it must be appended her
| Binary to ASCII | 151 | 152 | binary-to-ascii | N/A (Text) |
| Binary to Decimal | 153 | 154 | binary-to-decimal | N/A (Text) |
| Binary to Hex | 155 | 156 | binary-to-hex | N/A (Text) |
| Amps to Watts | 157 | 158 | amps-to-watts | Multi-Variable |
| Amps to Watts | 149 | 150 | amps-to-watts | Multi-Variable |
| Amps to Kilowatts | 159 | 160 | amps-to-kilowatts | Multi-Variable |
| Amps to kVA | 161 | 162 | amps-to-kva | Multi-Variable |
| Carats to Grams | 163 | 164 | carats-to-grams | 0.2 |
@@ -62,6 +62,46 @@ Whenever a new calculator is published via the REST API, it must be appended her
| Grams to Pennyweights | 228 | 229 | grams-to-pennyweights | 0.643014931 |
| Grams to Troy Ounces | 230 | 231 | grams-to-troy-ounces | 0.0321507466 |
| Gray to Rad | 232 | 233 | gray-to-rad | 100.0 |
| Grams to Apothecary Ounces | 234 | 235 | grams-to-apothecary-ounces | 0.0321507466 |
| Grams to Carats | 236 | 237 | grams-to-carats | 5.0 |
| Grams to Grains | 238 | 239 | grams-to-grains | 15.4323584 |
| Horsepower to Kilowatts | 240 | 241 | horsepower-to-kilowatts | 0.745699872 |
| Hours to Days | 242 | 243 | hours-to-days | 0.0416666667 |
| Hours to Minutes | 244 | 245 | hours-to-minutes | 60.0 |
| Inches of Mercury to Pascals | 246 | 247 | inches-of-mercury-to-pascals | 3386.389 |
| Inches of Water to Pascals | 248 | 249 | inches-of-water-to-pascals | 249.08891 |
| Inches to Centimeters | 250 | 251 | inches-of-centimeters | 2.54 |
| Inches to Millimeters | 252 | 253 | inches-of-millimeters | 25.4 |
| Centigrams to Grams | 347 | 348 | centigrams-to-grams | 0.01 |
| Centiliters to Liters | 349 | 350 | centiliters-to-liters | 0.01 |
| Centimeters to Feet | 351 | 352 | centimeters-to-feet | 0.032808399 |
| Centimeters to Meters | 353 | 354 | centimeters-to-meters | 0.01 |
| Centimeters to Millimeters | 355 | 356 | centimeters-to-millimeters | 10.0 |
| Chains to Feet | 357 | 358 | chains-to-feet | 66.0 |
| Chains to Meters | 359 | 360 | chains-to-meters | 20.1168 |
| Cubic Centimeters to Cubic Inches | 361 | 362 | cubic-centimeters-to-cubic-inches | 0.0610237441 |
| Cubic Feet to Cubic Meters | 363 | 364 | cubic-feet-to-cubic-meters | 0.0283168466 |
| Cubic Meters to Liters | 365 | 366 | cubic-meters-to-liters | 1000.0 |
| Grams to Micrograms | 367 | 368 | grams-to-micrograms | 1000000.0 |
| Hectopascals to Pascals | 370 | 371 | hectopascals-to-pascals | 100.0 |
| Hectopascals to Millibars | 372 | 373 | hectopascals-to-millibars | 1.0 |
| Joules to Kilojoules | 374 | 375 | joules-to-kilojoules | 0.001 |
| Kilojoules to Joules | 376 | 377 | kilojoules-to-joules | 1000.0 |
| Micrograms to Grams | 378 | 379 | micrograms-to-grams | 1e-06 |
| Milligrams to Grams | 380 | 381 | milligrams-to-grams | 0.001 |
| Millibars to Pascals | 382 | 383 | millibars-to-pascals | 100.0 |
| Millimeters of Mercury to Pascals | 384 | 385 | millimeters-of-mercury-to-pascals | 133.322 |
| Millimeters of Mercury to Pascals | 384 | 385 | millimeters-of-mercury-to-pascals | 133.322 |
| Meters per second to Feet per second | 388 | 389 | meters-per-second-to-feet-per-second | 3.28084 |
| Meters per second to Miles per hour | 390 | 391 | meters-per-second-to-miles-per-hour | 2.23694 |
| Meters per second to Yards per second | 392 | 393 | meters-per-second-to-yards-per-second | 1.09361 |
| Micrograms to Milligrams | 394 | 395 | micrograms-to-milligrams | 0.001 |
| Micrometers to Millimeters | 396 | 397 | micrometers-to-millimeters | 0.001 |
| Milligrams to Micrograms | 398 | 399 | milligrams-to-micrograms | 1000.0 |
| Milliliters to Liters | 400 | 401 | milliliters-to-liters | 0.001 |
| Milliliters to Fluid Ounces | 402 | 403 | milliliters-to-fluid-ounces | 0.033814 |
| Millimeters to Centimeters | 404 | 405 | millimeters-to-centimeters | 0.1 |
| Millimeters to Inches | 406 | 407 | millimeters-to-inches | 0.0393701 |
## Backlog / To-Do
- [x] Acres to hectares
@@ -138,13 +178,13 @@ Whenever a new calculator is published via the REST API, it must be appended her
- [x] Hectares to acres
- [ ] Hex to binary
- [ ] Hex to decimal
- [ ] Horsepower to kilowatts
- [ ] Hours to days
- [ ] Hours to minutes
- [ ] Inches of mercury to pascals
- [ ] Inches of water to pascals
- [ ] Inches to centimeters
- [ ] Inches to millimeters
- [x] Horsepower to kilowatts
- [x] Hours to days
- [x] Hours to minutes
- [x] Inches of mercury to pascals
- [x] Inches of water to pascals
- [x] Inches to centimeters
- [x] Inches to millimeters
- [ ] Joules to calories
- [ ] Joules to ergs
- [ ] Kilocalories to kilojoules
@@ -171,8 +211,21 @@ Whenever a new calculator is published via the REST API, it must be appended her
- [ ] Lux to lumens
- [ ] Megabytes to gigabytes
- [ ] Megajoules to kilowatt-hours
- [ ] Megapascals to PSI
- [ ] Megapixels to resolution (geometric math only)
- Batch 7 Generation (Length, Volume, Mass)
- [x] Draft implementation plan for 10 calculators (Centimeters, Cubic Feet, etc.)
- [x] Write and execute the Python generation API script.
- [x] Programmatically perform bidirectional math verification.
- [x] Update `calculators_list.md` and check off backlog tasks.
- Batch 9 Generation (Speed, Metric Divisions)
- [x] Draft implementation plan for 10 calculators (Meters/sec, Micrometers, Milliliters).
- [x] Write and execute the Python generation API script.
- [x] Programmatically perform bidirectional math verification.
- [x] Update `calculators_list.md` and check off backlog tasks.
- Batch 10 Generation (Time, Data, Flow)
- [ ] Draft implementation plan for 10 calculators (Minutes to Hours, Gigabytes to Megabytes, etc.)
- [ ] Write and execute the Python generation API script.
- [ ] Programmatically perform bidirectional math verification.
- [ ] Update `calculators_list.md` and check off backlog tasks.
- [ ] Meters per second to feet per second
- [ ] Meters per second to miles per hour
- [ ] Meters per second to yards per second

52
fix_g_mg.py Normal file
View File

@@ -0,0 +1,52 @@
import urllib.request
import json
import base64
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element/"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
js_logic = """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {
window.initRetries++;
setTimeout(init, 100);
}
return;
}
i1.oninput = function() {
var v = parseFloat(i1.value);
if (isNaN(v)) { i2.value = ""; return; }
i2.value = parseFloat((v * 1000.0).toFixed(8));
};
i2.oninput = function() {
var v = parseFloat(i2.value);
if (isNaN(v)) { i1.value = ""; return; }
i1.value = parseFloat((v / 1000.0).toFixed(8));
};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) { i1.value = p.get('v1'); i1.oninput(); }
else if (p.has('v2')) { i2.value = p.get('v2'); i2.oninput(); }
}
init();
})();
</script>"""
eid = 225
print(f"Patching EID {eid}...")
data = {"content": js_logic}
req = urllib.request.Request(f"{url_base_kadence}{eid}", data=json.dumps(data).encode("utf-8"), headers=headers, method="PUT")
try:
urllib.request.urlopen(req, timeout=30)
print("--> Done")
except Exception as e:
print(f"--> Error: {e}")

316
mass_patch_logic.py Normal file
View File

@@ -0,0 +1,316 @@
import urllib.request
import json
import base64
import time
import re
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element/"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
def get_robust_js(factor, offset):
return f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {factor} + {offset}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat(((v - {offset}) / {factor}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
# Manual mapping for complex ones as they don't follow the 1:1 format in the list
complex_fixes = {
140: """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value;
let binary = "";
for (let i = 0; i < val.length; i++) {
let bin = val[i].charCodeAt(0).toString(2);
binary += ("00000000" + bin).slice(-8) + " ";
}
i2.value = binary.trim();
};
i2.oninput = function() {
let val = i2.value.replace(/\\s/g, "");
let text = "";
for (let i = 0; i < val.length; i += 8) {
let byte = val.substr(i, 8);
if (byte.length === 8) text += String.fromCharCode(parseInt(byte, 2));
}
i1.value = text;
};
}
init();
})();
</script>""",
152: """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i2.oninput = function() {
let val = i2.value;
let binary = "";
for (let i = 0; i < val.length; i++) {
let bin = val[i].charCodeAt(0).toString(2);
binary += ("00000000" + bin).slice(-8) + " ";
}
i1.value = binary.trim();
};
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
let text = "";
for (let i = 0; i < val.length; i += 8) {
let byte = val.substr(i, 8);
if (byte.length === 8) text += String.fromCharCode(parseInt(byte, 2));
}
i2.value = text;
};
}
init();
})();
</script>""",
154: """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
if (val) i2.value = parseInt(val, 2).toString(10);
else i2.value = "";
};
i2.oninput = function() {
let val = i2.value;
if (val) i1.value = parseInt(val, 10).toString(2);
else i1.value = "";
};
}
init();
})();
</script>""",
156: """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
if (val) i2.value = parseInt(val, 2).toString(16).toUpperCase();
else i2.value = "";
};
i2.oninput = function() {
let val = i2.value;
if (val) i1.value = parseInt(val, 16).toString(2);
else i1.value = "";
};
}
init();
})();
</script>""",
142: """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
158: """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
160: """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv / 1000).toFixed(4));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv * 1000 / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv * 1000 / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
162: """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv / 1000).toFixed(4));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv * 1000 / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv * 1000 / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>"""
}
def patch_element(eid, js):
print(f"Patching EID {eid}...")
data = {"content": js}
req = urllib.request.Request(f"{url_base_kadence}{eid}", data=json.dumps(data).encode("utf-8"), headers=headers, method="PUT")
try:
urllib.request.urlopen(req, timeout=30)
print("--> Done")
except Exception as e:
print(f"--> Error: {e}")
# Parse registry for standard factors
with open("calculators_list.md", "r") as f:
lines = f.readlines()
for line in lines:
if "|" not in line or "Calculator Name" in line or ":---" in line: continue
parts = [p.strip() for p in line.split("|")]
if len(parts) < 6: continue
eid = parts[3]
if not eid.isdigit(): continue
eid = int(eid)
factor_str = parts[5]
# Only patch recent ones (Batch 3-6)
if eid < 140 and eid != 108 and eid != 110 and eid != 112 and eid != 114 and eid != 116 and eid != 118 and eid != 120 and eid != 122 and eid != 124 and eid != 126 and eid != 128 and eid != 130 and eid != 132 and eid != 134 and eid != 136 and eid != 138:
continue
if eid in complex_fixes:
patch_element(eid, complex_fixes[eid])
else:
# standard 1:1 or offset
factor = 1.0
offset = 0.0
if "Linear Offset" in factor_str:
# Linear Offset (1.8x + 32)
# Linear Offset (5/9x - 17.778)
m = re.search(r'\((.*?)x \+ (.*?)\)', factor_str)
if not m: m = re.search(r'\((.*?)x - (.*?)\)', factor_str)
if m:
m_val = m.group(1)
if m_val == "1.8": factor = 1.8
elif m_val == "5/9": factor = 5/9
b_val = float(m.group(2))
if "-" in factor_str: offset = -b_val
else: offset = b_val
else:
print(f"Skipping {eid}: unparseable offset {factor_str}")
continue
else:
try:
factor = float(factor_str)
except:
print(f"Skipping {eid}: unparseable factor {factor_str}")
continue
patch_element(eid, get_robust_js(factor, offset))
time.sleep(1)
# Also patch Batch 6 explicitly if not in registry yet (I check previous command status)
# Batch 6 Element IDs: 234, 236, 238, 240
batch_6_extra = [
(234, 0.0321507466, 0), # Grams to Apothecary Ounces
(236, 5.0, 0), # Grams to Carats
(238, 15.4323584, 0), # Grams to Grains
(240, 0.745699872, 0) # Horsepower to Kilowatts
]
for eid, f, o in batch_6_extra:
if eid not in complex_fixes:
patch_element(eid, get_robust_js(f, o))
time.sleep(1)

58
patch_b6.py Normal file
View File

@@ -0,0 +1,58 @@
import urllib.request
import json
import base64
import time
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
def get_js(f):
return f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.r < 50) {{
window.r++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {f}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat((v / {f}).toFixed(8));
}};
}}
window.r = 0;
init();
}})();
</script>"""
units = [
(235, 0.0321507466), # Grams to Apothecary Ounces
(237, 5.0), # Grams to Carats
(239, 15.4323584), # Grams to Grains
(241, 0.745699872) # Horsepower to Kilowatts
]
for eid, f in units:
data = json.dumps({'content': get_js(f)}).encode('utf-8')
url = f'https://howdoyouconvert.com/wp-json/wp/v2/kadence_element/{eid}'
req = urllib.request.Request(url, data=data, headers=headers, method='PUT')
try:
urllib.request.urlopen(req)
print(f"Patched {eid}")
except Exception as e:
print(f"Error {eid}: {e}")
time.sleep(1)

304
patch_universal.py Normal file
View File

@@ -0,0 +1,304 @@
import urllib.request
import json
import base64
import time
import re
url_base_kadence = "https://howdoyouconvert.com/wp-json/wp/v2/kadence_element/"
creds = base64.b64encode(b"ben:6YGf wVxu gBpz pkqx BGZO lfVP").decode("utf-8")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + creds,
"User-Agent": "Mozilla/5.0"
}
def get_robust_js(factor, offset):
return f"""<script>
(function() {{
function init() {{
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) {{
if (window.initRetries === undefined) window.initRetries = 0;
if (window.initRetries < 50) {{
window.initRetries++;
setTimeout(init, 100);
}}
return;
}}
i1.oninput = function() {{
var v = parseFloat(i1.value);
if (isNaN(v)) {{ i2.value = ""; return; }}
i2.value = parseFloat((v * {factor} + {offset}).toFixed(8));
}};
i2.oninput = function() {{
var v = parseFloat(i2.value);
if (isNaN(v)) {{ i1.value = ""; return; }}
i1.value = parseFloat(((v - {offset}) / {factor}).toFixed(8));
}};
var p = new URLSearchParams(window.location.search);
if (p.has('v1')) {{ i1.value = p.get('v1'); i1.oninput(); }}
else if (p.has('v2')) {{ i2.value = p.get('v2'); i2.oninput(); }}
}}
init();
}})();
</script>"""
# Complex mapping (same as before)
complex_fixes_by_slug = {
"ascii-to-binary": """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value;
let binary = "";
for (let i = 0; i < val.length; i++) {
let bin = val[i].charCodeAt(0).toString(2);
binary += ("00000000" + bin).slice(-8) + " ";
}
i2.value = binary.trim();
};
i2.oninput = function() {
let val = i2.value.replace(/\\s/g, "");
let text = "";
for (let i = 0; i < val.length; i += 8) {
let byte = val.substr(i, 8);
if (byte.length === 8) text += String.fromCharCode(parseInt(byte, 2));
}
i1.value = text;
};
}
init();
})();
</script>""",
"binary-to-ascii": """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i2.oninput = function() {
let val = i2.value;
let binary = "";
for (let i = 0; i < val.length; i++) {
let bin = val[i].charCodeAt(0).toString(2);
binary += ("00000000" + bin).slice(-8) + " ";
}
i1.value = binary.trim();
};
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
let text = "";
for (let i = 0; i < val.length; i += 8) {
let byte = val.substr(i, 8);
if (byte.length === 8) text += String.fromCharCode(parseInt(byte, 2));
}
i2.value = text;
};
}
init();
})();
</script>""",
"binary-to-decimal": """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
if (val) i2.value = parseInt(val, 2).toString(10);
else i2.value = "";
};
i2.oninput = function() {
let val = i2.value;
if (val) i1.value = parseInt(val, 10).toString(2);
else i1.value = "";
};
}
init();
})();
</script>""",
"binary-to-hex": """<script>
(function() {
function init() {
var i1 = document.getElementById("input-1");
var i2 = document.getElementById("input-2");
if (!i1 || !i2) { setTimeout(init, 100); return; }
i1.oninput = function() {
let val = i1.value.replace(/\\s/g, "");
if (val) i2.value = parseInt(val, 2).toString(16).toUpperCase();
else i2.value = "";
};
i2.oninput = function() {
let val = i2.value;
if (val) i1.value = parseInt(val, 16).toString(2);
else i1.value = "";
};
}
init();
})();
</script>""",
"amps-to-volts": """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
"amps-to-watts": """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv).toFixed(3));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
"amps-to-kilowatts": """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv / 1000).toFixed(4));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv * 1000 / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv * 1000 / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>""",
"amps-to-kva": """<script>
(function() {
function init() {
var a = document.getElementById("input-1");
var v = document.getElementById("input-2");
var w = document.getElementById("input-3");
if (!a || !v || !w) { setTimeout(init, 100); return; }
function solve(lastId) {
let av = parseFloat(a.value), vv = parseFloat(v.value), wv = parseFloat(w.value);
if (lastId === '1' || lastId === '2') {
if (!isNaN(av) && !isNaN(vv)) w.value = parseFloat((av * vv / 1000).toFixed(4));
} else if (lastId === '3') {
if (!isNaN(wv)) {
if (!isNaN(av) && av !== 0) v.value = parseFloat((wv * 1000 / av).toFixed(2));
else if (!isNaN(vv) && vv !== 0) a.value = parseFloat((wv * 1000 / vv).toFixed(2));
}
}
}
a.oninput = () => solve('1'); v.oninput = () => solve('2'); w.oninput = () => solve('3');
}
init();
})();
</script>"""
}
def patch_element(eid, js):
print(f"Patching EID {eid}...")
data = {"content": js}
req = urllib.request.Request(f"{url_base_kadence}{eid}", data=json.dumps(data).encode("utf-8"), headers=headers, method="PUT")
try:
urllib.request.urlopen(req, timeout=30)
print("--> Done")
except Exception as e:
print(f"--> Error: {e}")
# 1. Load factors from registry
registry = {}
with open("calculators_list.md", "r") as f:
for line in f:
if "|" not in line or "Calculators Registry" in line or "---" in line: continue
parts = [p.strip() for p in line.split("|")]
if len(parts) < 6: continue
slug = parts[4].replace("-2", "")
factor_str = parts[5]
registry[slug] = factor_str
# 2. Load mapping
with open("/tmp/element_mapping.json", "r") as f:
mappings = json.load(f)
for m in mappings:
eid = m['eid']
raw_slug = m['slug']
base_slug = raw_slug.replace("-2", "")
if base_slug in complex_fixes_by_slug:
patch_element(eid, complex_fixes_by_slug[base_slug])
continue
if base_slug in registry:
factor_str = registry[base_slug]
factor = 1.0
offset = 0.0
if "Linear Offset" in factor_str:
match = re.search(r'\((.*?)x \+ (.*?)\)', factor_str)
if not match: match = re.search(r'\((.*?)x - (.*?)\)', factor_str)
if match:
m_val = match.group(1)
if m_val == "1.8": factor = 1.8
elif m_val == "5/9": factor = 5/9
b_val = float(match.group(2))
if "-" in factor_str: offset = -b_val
else: offset = b_val
else:
try:
factor = float(factor_str)
except:
print(f"Skipping {eid} ({base_slug}): unparseable factor {factor_str}")
continue
patch_element(eid, get_robust_js(factor, offset))
else:
print(f"Warning: Slug {base_slug} (EID {eid}) not in registry. Skipping.")
print("UNIVERSAL PATCH COMPLETE")

46
verify_batch_10.py Normal file
View File

@@ -0,0 +1,46 @@
import urllib.request
import json
import re
batch_10_results = [
{"url": "https://howdoyouconvert.com/calculator/megabytes-to-gigabytes/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/megajoules-to-kilowatt-hours/?ao_noptimize=1", "v1": 3.6, "expected_v2": 1, "m": 0.277778},
{"url": "https://howdoyouconvert.com/calculator/meters-to-feet/?ao_noptimize=1", "v1": 1, "expected_v2": 3.28084, "m": 3.28084},
{"url": "https://howdoyouconvert.com/calculator/meters-to-yards/?ao_noptimize=1", "v1": 1, "expected_v2": 1.09361, "m": 1.09361},
{"url": "https://howdoyouconvert.com/calculator/metric-tons-to-short-tons/?ao_noptimize=1", "v1": 1, "expected_v2": 1.10231, "m": 1.10231},
{"url": "https://howdoyouconvert.com/calculator/minutes-to-hours/?ao_noptimize=1", "v1": 60, "expected_v2": 1, "m": 0.0166667},
{"url": "https://howdoyouconvert.com/calculator/minutes-to-seconds/?ao_noptimize=1", "v1": 1, "expected_v2": 60, "m": 60.0},
{"url": "https://howdoyouconvert.com/calculator/nautical-miles-to-kilometers/?ao_noptimize=1", "v1": 1, "expected_v2": 1.852, "m": 1.852},
{"url": "https://howdoyouconvert.com/calculator/newtons-to-dynes/?ao_noptimize=1", "v1": 1, "expected_v2": 100000.0, "m": 100000.0},
{"url": "https://howdoyouconvert.com/calculator/ounces-to-grams/?ao_noptimize=1", "v1": 1, "expected_v2": 28.3495, "m": 28.3495}
]
headers = {"User-Agent": "Mozilla/5.0"}
for calc in batch_10_results:
print(f"\n--- Verifying {calc['url']} ---")
req = urllib.request.Request(calc['url'], headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30).read().decode("utf-8")
if "initRetries" in resp and "setTimeout(init, 100)" in resp:
print("Robust JS: OK")
else:
print("Robust JS: MISSING")
m_pattern = r'i2\.value = parseFloat\(\(v \* ([\d\.e\-]+)\)'
m = re.search(m_pattern, resp)
if m:
actual_m = float(m.group(1))
print(f"Multiplier: {actual_m} (Expected {calc['m']})")
if abs(actual_m - calc['m']) / (calc['m'] or 1) < 0.0001:
print("Math Match: OK")
else:
print("Math Match: FAIL")
else:
print("Multiplier: NOT FOUND")
except Exception as e:
print(f"Error: {e}")
print("\nVERIFICATION COMPLETE")

47
verify_batch_7.py Normal file
View File

@@ -0,0 +1,47 @@
import urllib.request
import json
import re
batch_7_results = [
{"url": "https://howdoyouconvert.com/calculator/centigrams-to-grams/?ao_noptimize=1", "v1": 100, "expected_v2": 1, "m": 0.01},
{"url": "https://howdoyouconvert.com/calculator/centiliters-to-liters/?ao_noptimize=1", "v1": 100, "expected_v2": 1, "m": 0.01},
{"url": "https://howdoyouconvert.com/calculator/centimeters-to-feet/?ao_noptimize=1", "v1": 30.48, "expected_v2": 0.99999999, "m": 0.032808399},
{"url": "https://howdoyouconvert.com/calculator/centimeters-to-meters/?ao_noptimize=1", "v1": 100, "expected_v2": 1, "m": 0.01},
{"url": "https://howdoyouconvert.com/calculator/centimeters-to-millimeters/?ao_noptimize=1", "v1": 1, "expected_v2": 10, "m": 10.0},
{"url": "https://howdoyouconvert.com/calculator/chains-to-feet/?ao_noptimize=1", "v1": 1, "expected_v2": 66, "m": 66.0},
{"url": "https://howdoyouconvert.com/calculator/chains-to-meters/?ao_noptimize=1", "v1": 1, "expected_v2": 20.1168, "m": 20.1168},
{"url": "https://howdoyouconvert.com/calculator/cubic-centimeters-to-cubic-inches/?ao_noptimize=1", "v1": 16.387064, "expected_v2": 1, "m": 0.0610237441},
{"url": "https://howdoyouconvert.com/calculator/cubic-feet-to-cubic-meters/?ao_noptimize=1", "v1": 35.3146667, "expected_v2": 1, "m": 0.0283168466},
{"url": "https://howdoyouconvert.com/calculator/cubic-meters-to-liters/?ao_noptimize=1", "v1": 1, "expected_v2": 1000, "m": 1000.0}
]
headers = {"User-Agent": "Mozilla/5.0"}
for calc in batch_7_results:
print(f"\n--- Verifying {calc['url']} ---")
req = urllib.request.Request(calc['url'], headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30).read().decode("utf-8")
# Check for robust JS
if "initRetries" in resp and "setTimeout(init, 100)" in resp:
print("Robust JS: OK")
else:
print("Robust JS: MISSING")
# Extract multiplier
m = re.search(r'v \* ([\d\.]+)', resp)
if m:
actual_m = float(m.group(1))
print(f"Multiplier: {actual_m} (Expected {calc['m']})")
if abs(actual_m - calc['m']) < 0.0000001:
print("Math Match: OK")
else:
print("Math Match: FAIL")
else:
print("Multiplier: NOT FOUND")
except Exception as e:
print(f"Error: {e}")
print("\nVERIFICATION COMPLETE")

49
verify_batch_8.py Normal file
View File

@@ -0,0 +1,49 @@
import urllib.request
import json
import re
batch_8_results = [
{"url": "https://howdoyouconvert.com/calculator/grams-to-micrograms/?ao_noptimize=1", "v1": 1, "expected_v2": 1000000, "m": 1000000.0},
{"url": "https://howdoyouconvert.com/calculator/grams-to-milligrams/?ao_noptimize=1", "v1": 1, "expected_v2": 1000, "m": 1000.0},
{"url": "https://howdoyouconvert.com/calculator/hectopascals-to-pascals/?ao_noptimize=1", "v1": 1, "expected_v2": 100, "m": 100.0},
{"url": "https://howdoyouconvert.com/calculator/hectopascals-to-millibars/?ao_noptimize=1", "v1": 1, "expected_v2": 1, "m": 1.0},
{"url": "https://howdoyouconvert.com/calculator/joules-to-kilojoules/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/kilojoules-to-joules/?ao_noptimize=1", "v1": 1, "expected_v2": 1000, "m": 1000.0},
{"url": "https://howdoyouconvert.com/calculator/micrograms-to-grams/?ao_noptimize=1", "v1": 1000000, "expected_v2": 1, "m": 0.000001},
{"url": "https://howdoyouconvert.com/calculator/milligrams-to-grams/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/millibars-to-pascals/?ao_noptimize=1", "v1": 1, "expected_v2": 100, "m": 100.0},
{"url": "https://howdoyouconvert.com/calculator/millimeters-of-mercury-to-pascals/?ao_noptimize=1", "v1": 1, "expected_v2": 133.322, "m": 133.322}
]
headers = {"User-Agent": "Mozilla/5.0"}
for calc in batch_8_results:
print(f"\n--- Verifying {calc['url']} ---")
req = urllib.request.Request(calc['url'], headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30).read().decode("utf-8")
# Check for robust JS
if "initRetries" in resp and "setTimeout(init, 100)" in resp:
print("Robust JS: OK")
else:
print("Robust JS: MISSING")
# Extract multiplier (using flexible regex for scientific notation if needed, but here they are standard)
# Match v * factor. The factor might be 1e-06
m_pattern = r'i2\.value = parseFloat\(\(v \* ([\d\.e\-]+)\)'
m = re.search(m_pattern, resp)
if m:
actual_m = float(m.group(1))
print(f"Multiplier: {actual_m} (Expected {calc['m']})")
if abs(actual_m - calc['m']) / (calc['m'] or 1) < 0.000001:
print("Math Match: OK")
else:
print("Math Match: FAIL")
else:
print("Multiplier: NOT FOUND")
except Exception as e:
print(f"Error: {e}")
print("\nVERIFICATION COMPLETE")

48
verify_batch_9.py Normal file
View File

@@ -0,0 +1,48 @@
import urllib.request
import json
import re
batch_9_results = [
{"url": "https://howdoyouconvert.com/calculator/meters-per-second-to-feet-per-second/?ao_noptimize=1", "v1": 1, "expected_v2": 3.28084, "m": 3.28084},
{"url": "https://howdoyouconvert.com/calculator/meters-per-second-to-miles-per-hour/?ao_noptimize=1", "v1": 10, "expected_v2": 22.3694, "m": 2.23694},
{"url": "https://howdoyouconvert.com/calculator/meters-per-second-to-yards-per-second/?ao_noptimize=1", "v1": 1, "expected_v2": 1.09361, "m": 1.09361},
{"url": "https://howdoyouconvert.com/calculator/micrograms-to-milligrams/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/micrometers-to-millimeters/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/milligrams-to-micrograms/?ao_noptimize=1", "v1": 1, "expected_v2": 1000, "m": 1000.0},
{"url": "https://howdoyouconvert.com/calculator/milliliters-to-liters/?ao_noptimize=1", "v1": 1000, "expected_v2": 1, "m": 0.001},
{"url": "https://howdoyouconvert.com/calculator/milliliters-to-fluid-ounces/?ao_noptimize=1", "v1": 100, "expected_v2": 3.3814, "m": 0.033814},
{"url": "https://howdoyouconvert.com/calculator/millimeters-to-centimeters/?ao_noptimize=1", "v1": 10, "expected_v2": 1, "m": 0.1},
{"url": "https://howdoyouconvert.com/calculator/millimeters-to-inches/?ao_noptimize=1", "v1": 25.4, "expected_v2": 1, "m": 0.0393701}
]
headers = {"User-Agent": "Mozilla/5.0"}
for calc in batch_9_results:
print(f"\n--- Verifying {calc['url']} ---")
req = urllib.request.Request(calc['url'], headers=headers)
try:
resp = urllib.request.urlopen(req, timeout=30).read().decode("utf-8")
# Check for robust JS
if "initRetries" in resp and "setTimeout(init, 100)" in resp:
print("Robust JS: OK")
else:
print("Robust JS: MISSING")
# Extract multiplier
m_pattern = r'i2\.value = parseFloat\(\(v \* ([\d\.e\-]+)\)'
m = re.search(m_pattern, resp)
if m:
actual_m = float(m.group(1))
print(f"Multiplier: {actual_m} (Expected {calc['m']})")
if abs(actual_m - calc['m']) / (calc['m'] or 1) < 0.000001:
print("Math Match: OK")
else:
print("Math Match: FAIL")
else:
print("Multiplier: NOT FOUND")
except Exception as e:
print(f"Error: {e}")
print("\nVERIFICATION COMPLETE")