<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sewlore Engineering Notes]]></title><description><![CDATA[Sewlore Engineering Notes]]></description><link>https://sewlore.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Sewlore Engineering Notes</title><link>https://sewlore.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 14 Oct 2026 13:51:25 GMT</lastBuildDate><atom:link href="https://sewlore.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Same measurement, different input rules: comparing sewing calculation packages]]></title><description><![CDATA[A measurement formula can stay the same while its input rules change. That matters when a sewing worksheet, browser tool or command-line script moves between packages. We compared ten small software c]]></description><link>https://sewlore.hashnode.dev/same-measurement-different-input-rules-comparing-sewing-calculation-packages</link><guid isPermaLink="true">https://sewlore.hashnode.dev/same-measurement-different-input-rules-comparing-sewing-calculation-packages</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Rust]]></category><dc:creator><![CDATA[Sewlore]]></dc:creator><pubDate>Sat, 10 Oct 2026 19:18:16 GMT</pubDate><content:encoded><![CDATA[<p>A measurement formula can stay the same while its input rules change. That matters when a sewing worksheet, browser tool or command-line script moves between packages. We compared ten small software cases using published Sewlore interfaces to identify their contract differences, rather than make a blanket claim that they are equivalent.</p>
<p>The versions were <a href="https://www.npmjs.com/package/@sewingselami/sewlore-sewing-math">npm’s @sewingselami/sewlore-sewing-math</a> 0.1.0, <a href="https://packagist.org/packages/sewlore/measurement-calculators">Packagist’s sewlore/measurement-calculators</a> 1.0.0 and <a href="https://crates.io/crates/sewlore-sewing-math/0.1.0">crates.io’s sewlore-sewing-math</a> 0.1.0. The <a href="https://github.com/gokimedia/sewlore-sewing-tools/tree/6a54ec08e8d4dc75b672ec64815c71da0160b950/examples/measurement-contract-comparison">companion harness</a> retains unchanged published source snapshots and SHA-256 values in <code>source-lock.json</code>; <code>python run.py</code> reproduces its ten-case comparison. No hosted pipeline is claimed.</p>
<p>There is an important language distinction. The Drupal module uses PHP to render its calculator block and configure an optional reference link, but its arithmetic runs in JavaScript. Our comparison executed that JavaScript, the npm functions and the Rust command-line program. It did not invent or test a separate PHP implementation. Minimal unchanged source snapshots were tied to the published versions and file hashes before execution.</p>
<h2>Unit support and input validation</h2>
<p>The straightforward case behaved as expected: converting one inch produced 2.54 centimetres in all three interfaces. Millimetres revealed the first difference. The npm conversion function accepts only centimetres and inches, while the Drupal arithmetic and Rust accept millimetres too. For 25.4mm to inches, the latter two returned one. We marked the npm case unsupported instead of inserting an adapter conversion and implying that the package provided it.</p>
<p>Negative input exposed another contract choice. Converting −1cm to inches returned approximately −0.3937007874 in npm. Drupal and Rust rejected the negative length. Neither outcome proves that one package is generally better. A signed coordinate or mathematical difference can be useful, while a physical length often needs a nonnegative constraint. An integration should choose and document the meaning of its input before calling the function.</p>
<p>One deliberately extreme case tested numerical range rather than sewing practice. Converting the positive binary floating-point value represented by <code>5e-324</code> centimetres to inches returned zero in both JavaScript converters. Rust rejected the conversion because it would turn a positive length into zero through underflow. This input is a synthetic software stress case, not a plausible fabric measurement. It illustrates why accepting a finite input does not automatically guarantee a useful converted result.</p>
<h2>Stretch recovery and undefined results</h2>
<p>The ordinary stretch example agreed across the implementations. Original 10cm, stretched 14cm and released 10.5cm produced 40% stretch, 5% residual change and 87.5% recovered extension. The first two percentages use original length as their denominator. Recovered extension uses the applied extension, which is 4cm here. When all three readings were 10cm, that last denominator was zero. All three interfaces preserved an undefined recovery value, represented as <code>null</code> in their JSON output.</p>
<p>A released reading below the original stayed visible. For 10cm, 15cm and 9.5cm, the results included −5% residual change and approximately 110% recovered extension, with an unusual-reading flag. The values were not clamped into a more comfortable range. Mixed units required more care: Rust normalized 10cm, 140mm and 10.5cm and returned the ordinary 40%, 5% and 87.5% result. The JavaScript stretch APIs require a common unit, so the comparison refused that mixed-unit input rather than treating 10 and 140 as directly comparable lengths.</p>
<h2>Check each print axis and their difference</h2>
<p>The print-scale case separated two questions. Against a 100mm target, widths and heights of 99.6mm and 100.4mm are each within a 0.5% threshold. Their difference is 0.8 percentage points, however, so npm and Rust also flagged the X/Y gap as excessive. The Drupal math export has no print-scale operation. A passing per-axis check therefore does not imply that the two directions behave uniformly, and no result here prescribes a printer correction.</p>
<h2>Reproduce the comparison</h2>
<p>The run generated 30 outcome records from 26 actual numerical calls; four entries were explicitly unsupported. All expected outcomes matched. The inputs were synthetic, and no physical fabric specimens, printer readings or empirical accuracy study were collected. The <a href="https://sewlore.com/pages/fabric-measurement-methods-guide">Sewlore measurement methods guide</a> gives the recording assumptions behind these calculations. AI assisted this comparison and explanatory draft; its evidence is execution of the published code with stated limitations.</p>
]]></content:encoded></item><item><title><![CDATA[Validate Measurement CSVs Before Calculating Percentage Change]]></title><description><![CDATA[A percentage calculation can be correct while the comparison is meaningless. A row might mix centimetres and millimetres, use zero as its before reading, or combine unrelated spans. Parsing every cell]]></description><link>https://sewlore.hashnode.dev/validate-measurement-csvs-before-calculating-percentage-change</link><guid isPermaLink="true">https://sewlore.hashnode.dev/validate-measurement-csvs-before-calculating-percentage-change</guid><category><![CDATA[Python]]></category><category><![CDATA[csv]]></category><dc:creator><![CDATA[Sewlore]]></dc:creator><pubDate>Wed, 07 Oct 2026 15:01:06 GMT</pubDate><content:encoded><![CDATA[<p>A percentage calculation can be correct while the comparison is meaningless. A row might mix centimetres and millimetres, use zero as its before reading, or combine unrelated spans. Parsing every cell as a float is therefore not enough. A useful measurement pipeline checks the record contract before applying the formula.</p>
<p>This tutorial uses the published <a href="https://pypi.org/project/sewlore-fabric-care/0.1.0/">sewlore-fabric-care 0.1.0 package</a>, an MIT Python API and local CLI. Every numerical example is hypothetical software input, not measured fabric data. AI assistance was used to prepare this article; its API contracts were checked against the published source and documentation.</p>
<h2>Choose the validation boundary deliberately</h2>
<p>The package exposes two CSV entry points. The lower-level validate_csv function accepts text, generic identifiers and free-text notes, with a one-million-character limit. It is useful inside a controlled application, but it does not implement the bounded anonymous-record policy.</p>
<p>The CLI uses validate_submission instead. That function accepts bytes, requires UTF-8 CSV, and applies a 128 KiB limit and a maximum of 250 nonempty records. Its ten-column header is fixed. Sample identifiers follow sample- plus one to six digits; care methods come from an explicit list, and notes must be empty. These restrictions reduce accidental free-text collection. They do not verify how a physical sample was measured.</p>
<p>An anonymous-policy failure in sample_id, care_method or notes rejects the whole file before calculation. Once that policy gate passes, core validation separates units or numeric errors row by row, allowing valid rows to continue.</p>
<pre><code class="language-python">from sewlore_fabric_care import BLANK_CSV, validate_submission

accepted, corrections = validate_submission(BLANK_CSV.encode("utf-8"))
assert accepted == [] and corrections == []
</code></pre>
<p>A header-only template is a valid empty collection. Treating it as a fabricated sample would change the meaning of the data. The <a href="https://sewlore-fabric-care.readthedocs.io/en/latest/">package documentation</a> describes the API boundary, export columns and strict policy separately.</p>
<h2>Keep units and shape assumptions in the record</h2>
<p>The columns are sample_id, before_unit, after_unit, before_length, before_width, after_length, after_width, care_method, rectangle_assumption and notes. Four before/after readings must be positive and finite. Within a row, before and after units must match and must be cm, mm or in. Different rows can use different supported units.</p>
<p>Consider these two hypothetical rows. The first is eligible for calculation. The second intentionally changes its after unit to mm; the strict policy returns a unit correction instead of silently deciding that the numbers were converted correctly.</p>
<pre><code class="language-python">from sewlore_fabric_care import BLANK_CSV, validate_submission

hypothetical = (
    BLANK_CSV
    + "sample-001,cm,cm,20,20,19,19.5,wash-and-dry,yes,\n"
    + "sample-002,cm,mm,20,20,190,195,wash,no,\n"
)
accepted, corrections = validate_submission(hypothetical.encode("utf-8"))
</code></pre>
<p>The rectangle flag is also a data contract. yes enables the area calculation; no or an empty flag omits it. Recording two spans does not establish that a sample remained rectangular. The software cannot inspect skew, irregular edges, marking technique or measurement uncertainty.</p>
<h2>Preserve the sign and multiply the remaining factors</h2>
<p>For each axis, signed contraction is 100 times one minus after divided by before. Positive means contraction; negative means expansion. An after length of 21 compared with a before length of 20 therefore gives -5%, rather than a clipped zero or an unsigned five.</p>
<pre><code class="language-python">from sewlore_fabric_care import calculate_changes, convert_length

# Hypothetical paired rectangular spans, expressed in millimetres.
changes = calculate_changes(200, 200, 190, 195, rectangle_assumption=True)
# Approximately +5%, +2.5% and +7.375% rectangular-area contraction.

length_mm = convert_length(0.625, "in", "mm")  # 15.875
</code></pre>
<p>The remaining length fraction is 0.95 and the remaining width fraction is 0.975. Multiplying them gives 0.92625 remaining area, so the reduction is 7.375%. Adding the two axis percentages would give 7.5% and double-count their overlap. This calculation assumes paired flat rectangles, rather than estimating an arbitrary shape.</p>
<p>Finite input alone is not a complete numeric guarantee. Very large or very small values can still produce an unrepresentable conversion or ratio. The Python calculation core raises ValueError for invalid ranges and unrepresentable results. Its positive-length conversion contract also differs from the separate JavaScript sewing-math helper, which permits signed offsets and zero.</p>
<h2>Separate accepted records from correction entries</h2>
<p>Export both streams explicitly. A correction is a reason to inspect a record, not an alternative measurement. In the local CLI, the count summary goes to stderr, while a selected CSV can go to stdout. This keeps a pipeline from receiving human-readable summaries mixed into its CSV data.</p>
<pre><code class="language-bash">python -m pip install sewlore-fabric-care==0.1.0
sewlore-fabric-care template --output blank.csv
sewlore-fabric-care validate readings.csv \
  --accepted accepted.csv --corrections corrections.csv
</code></pre>
<p>Exit code 0 means completed validation with no corrections, including an empty template; 1 means completed validation with corrections; 2 means a usage or file/destination error. Existing outputs are protected unless --overwrite is explicitly selected. Input/output aliases, including existing hard links, are rejected. Writes are not transactional, so an I/O failure can leave partial exports.</p>
<p>CSV quoting and formula-prefix handling in the export layer serve a different purpose from row validation. They preserve cell boundaries and reduce common spreadsheet interpretation problems. They are not a universal guarantee about every spreadsheet application, and they cannot repair a wrong unit or an unsupported physical assumption.</p>
<h2>Make the method reproducible without inventing data</h2>
<p>Keep the actual marking, direction, care process and waiting time in a separate method record. The <a href="https://sewlore.com/pages/fabric-measurement-methods-guide">measurement methods guide</a> explains what those context fields mean. Leave the machine template empty until real readings exist; keep personal information and free-text observations out of this strict input.</p>
<p>The <a href="https://github.com/gokimedia/sewlore-fabric-care">public package source</a> makes the policy and CLI behavior inspectable. A useful integration preserves its accepted/correction distinction and tests hypothetical edge cases before using real records. Passing validation establishes a supported numeric record, not fabric quality, garment fit or laboratory compliance.</p>
]]></content:encoded></item></channel></rss>